<commit_before>#include "client.h"
#include "gconsole.h"
#include "net_worm.h"
#include "particle.h"
#include "part_type.h"
#include "game/WormInputHandler.h"
#include "gusgame.h"
#include "network.h"
#include "player_options.h"
#include "encoding.h"
#include <memory>
#include "util/log.h"

#include "netstream.h"

Client::Client() : Net_Control(false)
{
	Net_setControlID(0);
	Net_setDebugName("Net_CLI");
}

void Client::Net_cbConnectResult(eNet_ConnectResult res) {
	if(res != eNet_ConnAccepted) {
		errors << "Client::Net_cbConnectResult: connection not accepted" << endl;
		return;
	}

	network.setClient(true);
	console.addLogMsg("* CONNECTION ACCEPTED");
	network.incConnCount();

	// earlier, we did the mod/level loading here
	// _reply contained two strings, containing level/mod name
	sendConsistencyInfo();
	Net_requestNetMode(NetConnID_server(), 1);
}

Client::~Client()
{
}

void Client::sendConsistencyInfo()
{
	std::auto_ptr<Net_BitStream> req(new Net_BitStream);
	req->addInt(Network::ConsistencyInfo, 8);
	req->addInt(Network::protocolVersion, 32);
	gusGame.addCRCs(req.get());
	Net_sendData( network.getServerID(), req.release(), eNet_ReliableOrdered );
}

void Client::Net_cbConnectionClosed(Net_ConnID _id, eNet_CloseReason _reason, Net_BitStream &_reasondata)
{
	network.decConnCount();
	switch( _reason )
	{
		case eNet_ClosedDisconnect:
		{
			Network::DConnEvents dcEvent = static_cast<Network::DConnEvents>( _reasondata.getInt(8) );
			switch( dcEvent )
			{
				case Network::ServerMapChange:
				{
					console.addLogMsg("* SERVER CHANGED MAP");
					network.olxReconnect(150);
					gusGame.reset(GusGame::ServerChangeMap);
				}
				break;
				case Network::Quit:
				{
					console.addLogMsg("* CONNECTION CLOSED BY SERVER");
					gusGame.reset(GusGame::ServerQuit);
				}
				break;
				case Network::Kick:
				{
					console.addLogMsg("* YOU WERE KICKED");
					gusGame.reset(GusGame::Kicked);
				}
				break;
				case Network::IncompatibleData:
				{
					console.addLogMsg("* YOU HAVE INCOMPATIBLE DATA");
					gusGame.reset(GusGame::IncompatibleData);
				}
				break;

				case Network::IncompatibleProtocol:
				{
					console.addLogMsg("* THE HOST RUNS AN INCOMPATIBLE VERSION OF VERMES");
					gusGame.reset(GusGame::IncompatibleProtocol);
				}
				break;

				default:
				{
					console.addLogMsg("* CONNECTION CLOSED BY DUNNO WHAT :O");
					gusGame.reset(GusGame::ServerQuit);
				}
				break;
			}
		}
		break;

		case eNet_ClosedTimeout:
			console.addLogMsg("* CONNECTION TIMEDOUT");
			gusGame.reset(GusGame::ServerQuit);
		break;

		case eNet_ClosedReconnect:
			console.addLogMsg("* CONNECTION RECONNECTED");
		break;

		default:
		break;
	}

	DLOG("A connection was closed");
}

void Client::Net_cbDataReceived( Net_ConnID id, Net_BitStream& data)
{
	int event = Encoding::decode(data, Network::ClientEvents::Max);
	switch(event)
	{
		case Network::ClientEvents::LuaEvents:
		{
			for(int t = Network::LuaEventGroup::GusGame;
				t < Network::LuaEventGroup::Max; ++t)
			{
				int c = data.getInt(8);
				for(int i = 0; i < c; ++i)
				{
					char const* name = data.getStringStatic();
					network.indexLuaEvent((Network::LuaEventGroup::type)t, name);
				}
			}
		}
		break;
	}
}

void Client::Net_cbNodeRequest_Dynamic( Net_ConnID _id, Net_ClassID _requested_class, Net_BitStream *_announcedata, eNet_NodeRole _role, Net_NodeID _net_id )
{
	// check the requested class
	if ( _requested_class == CWorm::classID )
	{
		if(_announcedata == NULL) {
			warnings << "Net_cbNodeRequest_Dynamic for CWorm without announce data" << endl;
			return;
		}

		int wormid = _announcedata->getInt(8);
		if(wormid < 0 || wormid >= MAX_WORMS) {
			warnings << "Net_cbNodeRequest_Dynamic for CWorm: wormid " << wormid << " invalid" << endl;
			return;
		}

		notes << "Net_cbNodeRequest_Dynamic for worm " << wormid << ", nodeid " << _net_id << endl;

		CWorm* worm = &cClient->getRemoteWorms()[wormid];
		if(!worm->isUsed()) {
			warnings << "Net_cbNodeRequest_Dynamic for CWorm: worm " << wormid << " is not used" << endl;
			return;
		}

		worm->NetWorm_Init(false);
	}else if ( _requested_class == CWormInputHandler::classID )
	{
		if(_announcedata == NULL) {
			warnings << "Net_cbNodeRequest_Dynamic for CWormInputHandler without announce data" << endl;
			return;
		}

		int wormid = _announcedata->getInt(8);
		if(wormid < 0 || wormid >= MAX_WORMS) {
			warnings << "Net_cbNodeRequest_Dynamic for CWormInputHandler: wormid " << wormid << " invalid" << endl;
			return;
		}

		CWorm* worm = &cClient->getRemoteWorms()[wormid];
		if(!worm->isUsed()) {
			warnings << "Net_cbNodeRequest_Dynamic for CWormInputHandler: worm " << wormid << " is not used" << endl;
			return;
		}

		if(worm->getLocal()) {
			warnings << "Net_cbNodeRequest_Dynamic for CWormInputHandler: worm " << wormid << ":" << worm->getName() << " is a local worm, so we should be authority" << endl;
			return;
		}

		// Creates a player class depending on the role
		CWormInputHandler* player = gusGame.addPlayer ( (_role == eNet_RoleOwner) ? GusGame::OWNER : GusGame::PROXY, worm );
		player->assignNetworkRole(false);

		if(worm->m_inputHandler) {
			warnings << "Net_cbNodeRequest_Dynamic: worm " << worm->getName() << " has already the following input handler set: "; warnings.flush();
			warnings << worm->m_inputHandler->name() << endl;
			worm->m_inputHandler->quit();
			worm->m_inputHandler = NULL;
		}

		worm->m_inputHandler = player;
	}else if( _requested_class == Particle::classID )
	{
		int typeIndex = Encoding::decode(*_announcedata, partTypeList.size());
		CWormInputHandler* owner = gusGame.findPlayerWithID(_announcedata->getInt(32));
		newParticle_requested(partTypeList[typeIndex], Vec(), Vec(), 1, owner, Angle());
	}else
	{
		console.addLogMsg("* ERROR: INVALID DYNAMIC NODE REQUEST");
	}

}

<commit_msg>same fix again: server is always authority<commit_after>#include "client.h"
#include "gconsole.h"
#include "net_worm.h"
#include "particle.h"
#include "part_type.h"
#include "game/WormInputHandler.h"
#include "gusgame.h"
#include "network.h"
#include "player_options.h"
#include "encoding.h"
#include <memory>
#include "util/log.h"

#include "netstream.h"

Client::Client() : Net_Control(false)
{
	Net_setControlID(0);
	Net_setDebugName("Net_CLI");
}

void Client::Net_cbConnectResult(eNet_ConnectResult res) {
	if(res != eNet_ConnAccepted) {
		errors << "Client::Net_cbConnectResult: connection not accepted" << endl;
		return;
	}

	network.setClient(true);
	console.addLogMsg("* CONNECTION ACCEPTED");
	network.incConnCount();

	// earlier, we did the mod/level loading here
	// _reply contained two strings, containing level/mod name
	sendConsistencyInfo();
	Net_requestNetMode(NetConnID_server(), 1);
}

Client::~Client()
{
}

void Client::sendConsistencyInfo()
{
	std::auto_ptr<Net_BitStream> req(new Net_BitStream);
	req->addInt(Network::ConsistencyInfo, 8);
	req->addInt(Network::protocolVersion, 32);
	gusGame.addCRCs(req.get());
	Net_sendData( network.getServerID(), req.release(), eNet_ReliableOrdered );
}

void Client::Net_cbConnectionClosed(Net_ConnID _id, eNet_CloseReason _reason, Net_BitStream &_reasondata)
{
	network.decConnCount();
	switch( _reason )
	{
		case eNet_ClosedDisconnect:
		{
			Network::DConnEvents dcEvent = static_cast<Network::DConnEvents>( _reasondata.getInt(8) );
			switch( dcEvent )
			{
				case Network::ServerMapChange:
				{
					console.addLogMsg("* SERVER CHANGED MAP");
					network.olxReconnect(150);
					gusGame.reset(GusGame::ServerChangeMap);
				}
				break;
				case Network::Quit:
				{
					console.addLogMsg("* CONNECTION CLOSED BY SERVER");
					gusGame.reset(GusGame::ServerQuit);
				}
				break;
				case Network::Kick:
				{
					console.addLogMsg("* YOU WERE KICKED");
					gusGame.reset(GusGame::Kicked);
				}
				break;
				case Network::IncompatibleData:
				{
					console.addLogMsg("* YOU HAVE INCOMPATIBLE DATA");
					gusGame.reset(GusGame::IncompatibleData);
				}
				break;

				case Network::IncompatibleProtocol:
				{
					console.addLogMsg("* THE HOST RUNS AN INCOMPATIBLE VERSION OF VERMES");
					gusGame.reset(GusGame::IncompatibleProtocol);
				}
				break;

				default:
				{
					console.addLogMsg("* CONNECTION CLOSED BY DUNNO WHAT :O");
					gusGame.reset(GusGame::ServerQuit);
				}
				break;
			}
		}
		break;

		case eNet_ClosedTimeout:
			console.addLogMsg("* CONNECTION TIMEDOUT");
			gusGame.reset(GusGame::ServerQuit);
		break;

		case eNet_ClosedReconnect:
			console.addLogMsg("* CONNECTION RECONNECTED");
		break;

		default:
		break;
	}

	DLOG("A connection was closed");
}

void Client::Net_cbDataReceived( Net_ConnID id, Net_BitStream& data)
{
	int event = Encoding::decode(data, Network::ClientEvents::Max);
	switch(event)
	{
		case Network::ClientEvents::LuaEvents:
		{
			for(int t = Network::LuaEventGroup::GusGame;
				t < Network::LuaEventGroup::Max; ++t)
			{
				int c = data.getInt(8);
				for(int i = 0; i < c; ++i)
				{
					char const* name = data.getStringStatic();
					network.indexLuaEvent((Network::LuaEventGroup::type)t, name);
				}
			}
		}
		break;
	}
}

void Client::Net_cbNodeRequest_Dynamic( Net_ConnID _id, Net_ClassID _requested_class, Net_BitStream *_announcedata, eNet_NodeRole _role, Net_NodeID _net_id )
{
	// check the requested class
	if ( _requested_class == CWorm::classID )
	{
		if(_announcedata == NULL) {
			warnings << "Net_cbNodeRequest_Dynamic for CWorm without announce data" << endl;
			return;
		}

		int wormid = _announcedata->getInt(8);
		if(wormid < 0 || wormid >= MAX_WORMS) {
			warnings << "Net_cbNodeRequest_Dynamic for CWorm: wormid " << wormid << " invalid" << endl;
			return;
		}

		notes << "Net_cbNodeRequest_Dynamic for worm " << wormid << ", nodeid " << _net_id << endl;

		CWorm* worm = &cClient->getRemoteWorms()[wormid];
		if(!worm->isUsed()) {
			warnings << "Net_cbNodeRequest_Dynamic for CWorm: worm " << wormid << " is not used" << endl;
			return;
		}

		worm->NetWorm_Init(false);
	}else if ( _requested_class == CWormInputHandler::classID )
	{
		if(_announcedata == NULL) {
			warnings << "Net_cbNodeRequest_Dynamic for CWormInputHandler without announce data" << endl;
			return;
		}

		int wormid = _announcedata->getInt(8);
		if(wormid < 0 || wormid >= MAX_WORMS) {
			warnings << "Net_cbNodeRequest_Dynamic for CWormInputHandler: wormid " << wormid << " invalid" << endl;
			return;
		}

		CWorm* worm = &cClient->getRemoteWorms()[wormid];
		if(!worm->isUsed()) {
			warnings << "Net_cbNodeRequest_Dynamic for CWormInputHandler: worm " << wormid << " is not used" << endl;
			return;
		}

		notes << "Net_cbNodeRequest_Dynamic: new player (node " << _net_id << ") for worm " << wormid << ", set to " << ((_role == eNet_RoleOwner) ? "owner" : "proxy") << endl;

		// Creates a player class depending on the role
		CWormInputHandler* player = gusGame.addPlayer ( (_role == eNet_RoleOwner) ? GusGame::OWNER : GusGame::PROXY, worm );
		player->assignNetworkRole(false);

		if(worm->m_inputHandler) {
			warnings << "Net_cbNodeRequest_Dynamic: worm " << worm->getName() << " has already the following input handler set: "; warnings.flush();
			warnings << worm->m_inputHandler->name() << endl;
			worm->m_inputHandler->quit();
			worm->m_inputHandler = NULL;
		}

		worm->m_inputHandler = player;
	}else if( _requested_class == Particle::classID )
	{
		int typeIndex = Encoding::decode(*_announcedata, partTypeList.size());
		CWormInputHandler* owner = gusGame.findPlayerWithID(_announcedata->getInt(32));
		newParticle_requested(partTypeList[typeIndex], Vec(), Vec(), 1, owner, Angle());
	}else
	{
		console.addLogMsg("* ERROR: INVALID DYNAMIC NODE REQUEST");
	}

}

<|endoftext|>


<commit_before>//
//  i8255.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 01/08/2017.
//  Copyright © 2017 Thomas Harte. All rights reserved.
//

#ifndef i8255_hpp
#define i8255_hpp

namespace Intel {
namespace i8255 {

class PortHandler {
	public:
		void set_value(int port, uint8_t value) {}
		uint8_t get_value(int port) { return 0xff; }
};

// TODO: most of the implementation below. Right now it just blindly passes data in all directions,
// ignoring operation mode. But at least it establishes proper ownership and hand-off of decision making.
template <class T> class i8255 {
	public:
		i8255(T &port_handler) : control_(0), outputs_{0, 0, 0}, port_handler_(port_handler) {}

		void set_register(int address, uint8_t value) {
			switch(address & 3) {
				case 0:
					if(!(control_ & 0x10)) {
						// TODO: so what would output be when switching from input to output mode?
						outputs_[0] = value; port_handler_.set_value(0, value);
					}
				break;
				case 1:
					if(!(control_ & 0x02)) {
						outputs_[1] = value; port_handler_.set_value(1, value);
					}
				break;
				case 2:	outputs_[2] = value; port_handler_.set_value(2, value);	break;
				case 3:
					if(value & 0x80) {
						control_ = value;
					} else {
						if(value & 1) {
							outputs_[2] |= 1 << ((value >> 1)&7);
						} else {
							outputs_[2] &= ~(1 << ((value >> 1)&7));
						}
					}
					update_outputs();
				break;
			}
		}

		uint8_t get_register(int address) {
			switch(address & 3) {
				case 0:	return (control_ & 0x10) ? port_handler_.get_value(0) : outputs_[0];
				case 1:	return (control_ & 0x02) ? port_handler_.get_value(1) : outputs_[1];
				case 2:	{
					if(!(control_ & 0x09)) return outputs_[2];
					uint8_t input = port_handler_.get_value(2);
					return ((control_ & 0x01) ? (input & 0x0f) : (outputs_[2] & 0x0f)) | ((control_ & 0x08) ? (input & 0xf0) : (outputs_[2] & 0xf0));
				}
				case 3:	return control_;
			}
			return 0xff;
		}

	private:
		void update_outputs() {
			port_handler_.set_value(0, outputs_[0]);
			port_handler_.set_value(1, outputs_[1]);
			port_handler_.set_value(2, outputs_[2]);
		}

		uint8_t control_;
		uint8_t outputs_[3];
		T &port_handler_;
};

}
}

#endif /* i8255_hpp */
<commit_msg>Improved comments.<commit_after>//
//  i8255.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 01/08/2017.
//  Copyright © 2017 Thomas Harte. All rights reserved.
//

#ifndef i8255_hpp
#define i8255_hpp

namespace Intel {
namespace i8255 {

class PortHandler {
	public:
		void set_value(int port, uint8_t value) {}
		uint8_t get_value(int port) { return 0xff; }
};

// TODO: Modes 1 and 2.
template <class T> class i8255 {
	public:
		i8255(T &port_handler) : control_(0), outputs_{0, 0, 0}, port_handler_(port_handler) {}

		/*!
			Stores the value @c value to the register at @c address. If this causes a change in 8255 output
			then the PortHandler will be informed.
		*/
		void set_register(int address, uint8_t value) {
			switch(address & 3) {
				case 0:
					if(!(control_ & 0x10)) {
						// TODO: so what would output be when switching from input to output mode?
						outputs_[0] = value; port_handler_.set_value(0, value);
					}
				break;
				case 1:
					if(!(control_ & 0x02)) {
						outputs_[1] = value; port_handler_.set_value(1, value);
					}
				break;
				case 2:	outputs_[2] = value; port_handler_.set_value(2, value);	break;
				case 3:
					if(value & 0x80) {
						control_ = value;
					} else {
						if(value & 1) {
							outputs_[2] |= 1 << ((value >> 1)&7);
						} else {
							outputs_[2] &= ~(1 << ((value >> 1)&7));
						}
					}
					update_outputs();
				break;
			}
		}

		/*!
			Obtains the current value for the register at @c address. If this provides a reading
			of input then the PortHandler will be queried.
		*/
		uint8_t get_register(int address) {
			switch(address & 3) {
				case 0:	return (control_ & 0x10) ? port_handler_.get_value(0) : outputs_[0];
				case 1:	return (control_ & 0x02) ? port_handler_.get_value(1) : outputs_[1];
				case 2:	{
					if(!(control_ & 0x09)) return outputs_[2];
					uint8_t input = port_handler_.get_value(2);
					return ((control_ & 0x01) ? (input & 0x0f) : (outputs_[2] & 0x0f)) | ((control_ & 0x08) ? (input & 0xf0) : (outputs_[2] & 0xf0));
				}
				case 3:	return control_;
			}
			return 0xff;
		}

	private:
		void update_outputs() {
			port_handler_.set_value(0, outputs_[0]);
			port_handler_.set_value(1, outputs_[1]);
			port_handler_.set_value(2, outputs_[2]);
		}

		uint8_t control_;
		uint8_t outputs_[3];
		T &port_handler_;
};

}
}

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


<commit_before>/***************************************************************************
 *   Copyright (c) 2016 Victor Titov (DeepSOIC)      <vv.titov@gmail.com>  *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  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 Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <Precision.hxx>
#endif

#include "FeatureOffset.h"

using namespace Part;

const char* Part::Offset::ModeEnums[]= {"Skin","Pipe", "RectoVerso",NULL};
const char* Part::Offset::JoinEnums[]= {"Arc","Tangent", "Intersection",NULL};

PROPERTY_SOURCE(Part::Offset, Part::Feature)

Offset::Offset()
{
    ADD_PROPERTY_TYPE(Source,(0),"Offset",App::Prop_None,"Source shape");
    ADD_PROPERTY_TYPE(Value,(1.0),"Offset",App::Prop_None,"Offset value");
    ADD_PROPERTY_TYPE(Mode,(long(0)),"Offset",App::Prop_None,"Mode");
    Mode.setEnums(ModeEnums);
    ADD_PROPERTY_TYPE(Join,(long(0)),"Offset",App::Prop_None,"Join type");
    Join.setEnums(JoinEnums);
    ADD_PROPERTY_TYPE(Intersection,(false),"Offset",App::Prop_None,"Intersection");
    ADD_PROPERTY_TYPE(SelfIntersection,(false),"Offset",App::Prop_None,"Self Intersection");
    ADD_PROPERTY_TYPE(Fill,(false),"Offset",App::Prop_None,"Fill offset");
}

Offset::~Offset()
{

}

short Offset::mustExecute() const
{
    if (Source.isTouched())
        return 1;
    if (Value.isTouched())
        return 1;
    if (Mode.isTouched())
        return 1;
    if (Join.isTouched())
        return 1;
    if (Intersection.isTouched())
        return 1;
    if (SelfIntersection.isTouched())
        return 1;
    if (Fill.isTouched())
        return 1;
    return 0;
}

App::DocumentObjectExecReturn *Offset::execute(void)
{
    App::DocumentObject* source = Source.getValue();
    if (!(source && source->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())))
        return new App::DocumentObjectExecReturn("No source shape linked.");
    double offset = Value.getValue();
    double tol = Precision::Confusion();
    bool inter = Intersection.getValue();
    bool self = SelfIntersection.getValue();
    short mode = (short)Mode.getValue();
    short join = (short)Join.getValue();
    bool fill = Fill.getValue();
    const TopoShape& shape = static_cast<Part::Feature*>(source)->Shape.getShape();
    if (fabs(offset) > 2*tol)
        this->Shape.setValue(shape.makeOffsetShape(offset, tol, inter, self, mode, join, fill));
    else
        this->Shape.setValue(shape);
    return App::DocumentObject::StdReturn;
}

//-------------------------------------------------------------------------------------------------------

PROPERTY_SOURCE(Part::Offset2D, Part::Offset)

Offset2D::Offset2D()
{
    this->SelfIntersection.setStatus(App::Property::Status::Hidden, true);
    this->Mode.setValue(1); //switch to Pipe mode by default, because skin mode does not function properly on closed profiles.
}

Offset2D::~Offset2D()
{

}

short Offset2D::mustExecute() const
{
    if (Source.isTouched())
        return 1;
    if (Value.isTouched())
        return 1;
    if (Mode.isTouched())
        return 1;
    if (Join.isTouched())
        return 1;
    if (Fill.isTouched())
        return 1;
    if (Intersection.isTouched())
        return 1;
    return 0;
}

App::DocumentObjectExecReturn *Offset2D::execute(void)
{
    App::DocumentObject* source = Source.getValue();
    if (!(source && source->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())))
        return new App::DocumentObjectExecReturn("No source shape linked.");
    double offset = Value.getValue();
    short mode = (short)Mode.getValue();
    short join = (short)Join.getValue();
    bool fill = Fill.getValue();
    bool inter = Intersection.getValue();
    if (mode == 2)
        return new App::DocumentObjectExecReturn("Mode 'Recto-Verso' is not supported for 2D offset.");
    const TopoShape& shape = static_cast<Part::Feature*>(source)->Shape.getShape();
    this->Shape.setValue(shape.makeOffset2D(offset, join, fill, mode == 0, inter));
    return App::DocumentObject::StdReturn;
}
<commit_msg>set global scope of Part offset to use it with PD bodies<commit_after>/***************************************************************************
 *   Copyright (c) 2016 Victor Titov (DeepSOIC)      <vv.titov@gmail.com>  *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  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 Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <Precision.hxx>
#endif

#include "FeatureOffset.h"

using namespace Part;

const char* Part::Offset::ModeEnums[]= {"Skin","Pipe", "RectoVerso",NULL};
const char* Part::Offset::JoinEnums[]= {"Arc","Tangent", "Intersection",NULL};

PROPERTY_SOURCE(Part::Offset, Part::Feature)

Offset::Offset()
{
    ADD_PROPERTY_TYPE(Source,(0),"Offset",App::Prop_None,"Source shape");
    ADD_PROPERTY_TYPE(Value,(1.0),"Offset",App::Prop_None,"Offset value");
    ADD_PROPERTY_TYPE(Mode,(long(0)),"Offset",App::Prop_None,"Mode");
    Mode.setEnums(ModeEnums);
    ADD_PROPERTY_TYPE(Join,(long(0)),"Offset",App::Prop_None,"Join type");
    Join.setEnums(JoinEnums);
    ADD_PROPERTY_TYPE(Intersection,(false),"Offset",App::Prop_None,"Intersection");
    ADD_PROPERTY_TYPE(SelfIntersection,(false),"Offset",App::Prop_None,"Self Intersection");
    ADD_PROPERTY_TYPE(Fill,(false),"Offset",App::Prop_None,"Fill offset");

    Source.setScope(App::LinkScope::Global);
}

Offset::~Offset()
{

}

short Offset::mustExecute() const
{
    if (Source.isTouched())
        return 1;
    if (Value.isTouched())
        return 1;
    if (Mode.isTouched())
        return 1;
    if (Join.isTouched())
        return 1;
    if (Intersection.isTouched())
        return 1;
    if (SelfIntersection.isTouched())
        return 1;
    if (Fill.isTouched())
        return 1;
    return 0;
}

App::DocumentObjectExecReturn *Offset::execute(void)
{
    App::DocumentObject* source = Source.getValue();
    if (!(source && source->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())))
        return new App::DocumentObjectExecReturn("No source shape linked.");
    double offset = Value.getValue();
    double tol = Precision::Confusion();
    bool inter = Intersection.getValue();
    bool self = SelfIntersection.getValue();
    short mode = (short)Mode.getValue();
    short join = (short)Join.getValue();
    bool fill = Fill.getValue();
    const TopoShape& shape = static_cast<Part::Feature*>(source)->Shape.getShape();
    if (fabs(offset) > 2*tol)
        this->Shape.setValue(shape.makeOffsetShape(offset, tol, inter, self, mode, join, fill));
    else
        this->Shape.setValue(shape);
    return App::DocumentObject::StdReturn;
}

//-------------------------------------------------------------------------------------------------------

PROPERTY_SOURCE(Part::Offset2D, Part::Offset)

Offset2D::Offset2D()
{
    this->SelfIntersection.setStatus(App::Property::Status::Hidden, true);
    this->Mode.setValue(1); //switch to Pipe mode by default, because skin mode does not function properly on closed profiles.
}

Offset2D::~Offset2D()
{

}

short Offset2D::mustExecute() const
{
    if (Source.isTouched())
        return 1;
    if (Value.isTouched())
        return 1;
    if (Mode.isTouched())
        return 1;
    if (Join.isTouched())
        return 1;
    if (Fill.isTouched())
        return 1;
    if (Intersection.isTouched())
        return 1;
    return 0;
}

App::DocumentObjectExecReturn *Offset2D::execute(void)
{
    App::DocumentObject* source = Source.getValue();
    if (!(source && source->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())))
        return new App::DocumentObjectExecReturn("No source shape linked.");
    double offset = Value.getValue();
    short mode = (short)Mode.getValue();
    short join = (short)Join.getValue();
    bool fill = Fill.getValue();
    bool inter = Intersection.getValue();
    if (mode == 2)
        return new App::DocumentObjectExecReturn("Mode 'Recto-Verso' is not supported for 2D offset.");
    const TopoShape& shape = static_cast<Part::Feature*>(source)->Shape.getShape();
    this->Shape.setValue(shape.makeOffset2D(offset, join, fill, mode == 0, inter));
    return App::DocumentObject::StdReturn;
}
<|endoftext|>


<commit_before>/**********************************************************************************
 * Copyright (C) 2011 by Hugo Stefan Kaus Puhlmann                                *
 * 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 "GameWorld.hpp"
#include <iostream>
#include <GL/glfw.h>

using hstefan::game::GameWorld;
using hstefan::game::GameObject;
GameWorld* GameWorld::_instance = new GameWorld();

typedef std::deque<GameObject*>::iterator deque_iter;

void GameWorld::update()
{
   deque_iter it_end = game_objs.end();
   for(deque_iter it = game_objs.begin(); it != it_end; ++it)
      (*it)->update();
}

void GameWorld::render()
{
   deque_iter it_end = game_objs.end();
   for(deque_iter it = game_objs.begin(); it != it_end; ++it)
      (*it)->render();
}

void GameWorld::addObject(GameObject* gam)
{
   game_objs.push_back(gam);
}
<commit_msg>If the object returns true when done method is called, he's removed from GameWorld<commit_after>/**********************************************************************************
 * Copyright (C) 2011 by Hugo Stefan Kaus Puhlmann                                *
 * 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 "GameWorld.hpp"
#include <iostream>
#include <GL/glfw.h>

using hstefan::game::GameWorld;
using hstefan::game::GameObject;
GameWorld* GameWorld::_instance = new GameWorld();

typedef std::deque<GameObject*>::iterator deque_iter;

void GameWorld::update()
{
   deque_iter it_end = game_objs.end();
   for(deque_iter it = game_objs.begin(); it != it_end; ++it)
   {
      if(!(*it)->done())
         (*it)->update();
      else
         game_objs.erase(it);
   }
}

void GameWorld::render()
{
   deque_iter it_end = game_objs.end();
   for(deque_iter it = game_objs.begin(); it != it_end; ++it)
      (*it)->render();
}

void GameWorld::addObject(GameObject* gam)
{
   game_objs.push_back(gam);
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// socket_base.cpp
//
// Identification: src/wire/socket_base.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "wire/socket_base.h"
#include "wire/wire.h"
#include "common/exception.h"

#include <sys/un.h>
#include <string>

namespace peloton {
namespace wire {

template <typename B>
bool SocketManager<B>::RefillReadBuffer() {
  ssize_t bytes_read;

  // our buffer is to be emptied
  rbuf.Reset();

  // return explicitly
  for (;;) {
    //  try to fill the available space in the buffer
    bytes_read = read(sock_fd, &rbuf.buf[rbuf.buf_ptr],
                      SOCKET_BUFFER_SIZE - rbuf.buf_size);

    if (bytes_read < 0) {
		// Some other error occurred, close the socket, remove
		// the event and free the client structure.
    	switch(errno) {
		  case EINTR:
			  continue;
			  break;
		  case EAGAIN:
			  LOG_INFO("Error Reading: EAGAIN");
			  break;
		  case EBADF:
			  LOG_INFO("Error Reading: EBADF");
			  break;
		  case EDESTADDRREQ:
			  LOG_INFO("Error Reading: EDESTADDRREQ");
			  break;
		  case EDQUOT:
			  LOG_INFO("Error Reading: EDQUOT");
			  break;
		  case EFAULT:
			  LOG_INFO("Error Reading: EFAULT");
			  break;
		  case EFBIG:
			  LOG_INFO("Error Reading: EFBIG");
			  break;
		  case EINVAL:
			  LOG_INFO("Error Reading: EINVAL");
			  break;
		  case EIO:
			  LOG_INFO("Error Reading: EIO");
			  break;
		  case ENOSPC:
			  LOG_INFO("Error Reading: ENOSPC");
			  break;
		  case EPIPE:
			  LOG_INFO("Error Reading: EPIPE");
			  break;
		  default:
			  LOG_INFO("Error Reading: UNKNOWN");
		  }
      return false;
    }

    if (bytes_read == 0) {
	  // If the length of bytes returned by read is 0, this means
	  // that the client disconnected, remove the read event and the
	  // free the client structure.
      return false;
    }

    // read success, update buffer size
    rbuf.buf_size += bytes_read;

    // reset buffer ptr, to cover special case
    rbuf.buf_ptr = 0;
    return true;
  }
}

template <typename B>
bool SocketManager<B>::FlushWriteBuffer() {
  fd_set rset;
  struct timeval timeout;
  ssize_t written_bytes = 0;
  wbuf.buf_ptr = 0;
  // still outstanding bytes
  while ((int)wbuf.buf_size - written_bytes > 0) {
	  while(written_bytes <= 0){
			written_bytes = write(sock_fd, &wbuf.buf[wbuf.buf_ptr], wbuf.buf_size);
			if (written_bytes < 0) {
			  switch(errno) {
			  case EINTR:
				  continue;
				  break;
			  case EAGAIN:
				  LOG_INFO("Error Writing: EAGAIN");
				  break;
			  case EBADF:
				  LOG_INFO("Error Writing: EBADF");
				  break;
			  case EDESTADDRREQ:
				  LOG_INFO("Error Writing: EDESTADDRREQ");
				  break;
			  case EDQUOT:
				  LOG_INFO("Error Writing: EDQUOT");
				  break;
			  case EFAULT:
				  LOG_INFO("Error Writing: EFAULT");
				  break;
			  case EFBIG:
				  LOG_INFO("Error Writing: EFBIG");
				  break;
			  case EINVAL:
				  LOG_INFO("Error Writing: EINVAL");
				  break;
			  case EIO:
				  LOG_INFO("Error Writing: EIO");
				  break;
			  case ENOSPC:
				  LOG_INFO("Error Writing: ENOSPC");
				  break;
			  case EPIPE:
				  LOG_INFO("Error Writing: EPIPE");
				  break;
			  default:
				  LOG_INFO("Error Writing: UNKNOWN");
			  }
			  if (errno == EINTR) {
				// interrupts are ok, try again
				written_bytes = 0;
				continue;
			  } else if (errno == EAGAIN) {
				  FD_ZERO (&rset);
				  FD_SET (sock_fd, &rset);
				  timeout.tv_sec = 5;
				  written_bytes = select(sock_fd + 1, &rset, NULL, NULL, &timeout);
				  if (written_bytes < 0) {
					  LOG_INFO("written_bytes < 0 after select. Fatal");
					  exit(EXIT_FAILURE);
				  } else if (written_bytes == 0) {
					  // timed out without writing any data
					  LOG_INFO("Timeout without writing");
				  }
				  // else, socket is now readable, so loop back up and do the read() again
				  written_bytes = 0;
				  continue;
			  }
			  else {
				// fatal errors
				return false;
			  }
			}

			// weird edge case?
			if (written_bytes == 0 && wbuf.buf_size != 0) {
				LOG_INFO("Not all data is written");
			  // fatal
			  return false;
			}
	  }

    // update bookkeping
    wbuf.buf_ptr += written_bytes;
    wbuf.buf_size -= written_bytes;
  }

  // buffer is empty
  wbuf.Reset();

  // we are ok
  return true;
}

template <typename B>
bool SocketManager<B>::CanRead() {
  // Size of header (msg type + size)
  uint32_t header_size = sizeof(int32_t) + 1;
  uint32_t pkt_size = 0;
  // Size of available data for read
  size_t window = rbuf.buf_size - rbuf.buf_ptr;
  // If can read header
  if(header_size <= window) {
    PktBuf dummy_pkt;
	// Read the header size
	dummy_pkt.insert(std::end(dummy_pkt), std::begin(rbuf.buf) + rbuf.buf_ptr,
            std::begin(rbuf.buf) + rbuf.buf_ptr + header_size);
	// Get size of message
	std::copy(dummy_pkt.begin() + 1, dummy_pkt.end(),
	        reinterpret_cast<uchar *>(&pkt_size));
	pkt_size = ntohl(pkt_size) - sizeof(int32_t);
	// If header and size is larger than window, don't read untill receive a
	// read callback and buffer is refilled
	if(header_size + pkt_size > window) {
	  	return false;
	}
  }
  else {
	return false;
  }
  return true;
}

/*
 * read - Tries to read "bytes" bytes into packet's buffer. Returns true on
 * success.
 * 		false on failure. B can be any STL container.
 */
template <typename B>
bool SocketManager<B>::ReadBytes(B &pkt_buf, size_t bytes) {
  size_t window, pkt_buf_idx = 0;
  // while data still needs to be read
  while (bytes) {
    // how much data is available
    window = rbuf.buf_size - rbuf.buf_ptr;
    if (bytes <= window) {
      pkt_buf.insert(std::end(pkt_buf), std::begin(rbuf.buf) + rbuf.buf_ptr,
                     std::begin(rbuf.buf) + rbuf.buf_ptr + bytes);

      // move the pointer
      rbuf.buf_ptr += bytes;

      // move pkt_buf_idx as well
      pkt_buf_idx += bytes;

      return true;
    } else {
      // read what is available for non-trivial window
      if (window > 0) {
        pkt_buf.insert(std::end(pkt_buf), std::begin(rbuf.buf) + rbuf.buf_ptr,
                       std::begin(rbuf.buf) + rbuf.buf_size);

        // update bytes leftover
        bytes -= window;

        // update pkt_buf_idx
        pkt_buf_idx += window;
      }

      // refill buffer, reset buf ptr here
      if (!RefillReadBuffer()) {
        // nothing more to read, end
        return false;
      }
    }
  }

  return true;
}

template <typename B>
void SocketManager<B>::PrintWriteBuffer() {
	std::cout << "Write Buffer:" << std::endl;
	for(auto c : wbuf.buf) {
		std::cout << c << " ";
	}
	std::cout << std::endl;
}

template <typename B>
bool SocketManager<B>::BufferWriteBytes(B &pkt_buf, size_t len, uchar type) {
  size_t window, pkt_buf_ptr = 0;
  int len_nb;  // length in network byte order

  // check if we don't have enough space in the buffer
  if (wbuf.GetMaxSize() - wbuf.buf_ptr < 1 + sizeof(int32_t)) {
    // buffer needs to be flushed before adding header
	  std::cout << "FlushWriteBuffer due to not enough space" << std::endl;
	  PrintWriteBuffer();
    FlushWriteBuffer();
  }

  // assuming wbuf is now large enough to
  // fit type and size fields in one go
  if (type != 0) {
    // type shouldn't be ignored
    wbuf.buf[wbuf.buf_ptr++] = type;
  }

  // make len include its field size as well
  len_nb = htonl(len + sizeof(int32_t));

  // append the bytes of this integer in network-byte order
  std::copy(reinterpret_cast<uchar *>(&len_nb),
            reinterpret_cast<uchar *>(&len_nb) + 4,
            std::begin(wbuf.buf) + wbuf.buf_ptr);

  // move the write buffer pointer and update size of the socket buffer
  wbuf.buf_ptr += sizeof(int32_t);
  wbuf.buf_size = wbuf.buf_ptr;

  // fill the contents
  while (len) {
    window = wbuf.GetMaxSize() - wbuf.buf_ptr;
    if (len <= window) {
      // contents fit in the window, range copy "len" bytes
      std::copy(std::begin(pkt_buf) + pkt_buf_ptr,
                std::begin(pkt_buf) + pkt_buf_ptr + len,
                std::begin(wbuf.buf) + wbuf.buf_ptr);

      // Move the cursor and update size of socket buffer
      wbuf.buf_ptr += len;
      wbuf.buf_size = wbuf.buf_ptr;
      std::cout << "Filled the write buffer but not flushed yet" << std::endl;
      PrintWriteBuffer();
      return true;
    } else {
    	std::cout << "available window (" << window <<  ") is less than the length (" << len << ")" << std::endl;
        /* contents longer than socket buffer size, fill up the socket buffer
         *  with "window" bytes
         */
        std::copy(std::begin(pkt_buf) + pkt_buf_ptr,
                std::begin(pkt_buf) + pkt_buf_ptr + window,
                std::begin(wbuf.buf) + wbuf.buf_ptr);

        // move the packet's cursor
        pkt_buf_ptr += window;
        len -= window;

        wbuf.buf_size = wbuf.GetMaxSize();

        std::cout << "Before flushing write buffer..." << std::endl;
        PrintWriteBuffer();
        // write failure
        if (!FlushWriteBuffer()) {
          std::cout << "Failed to flush write buffer" << std::endl;
    	  return false;
        }
        else {
          std::cout << "Flushed write buffer successfully" << std::endl;
        }
    }
  }
  return true;
}

template <typename B>
void SocketManager<B>::CloseSocket() {
  for (;;) {
    int status = close(sock_fd);
    if (status < 0) {
      // failed close
      if (errno == EINTR) {
        // interrupted, try closing again
        continue;
      }
    }
    return;
  }
}

// explicit template instantiation for read_bytes
template class SocketManager<PktBuf>;

}  // End wire namespace
}  // End peloton namespace
<commit_msg>Debug write buffer<commit_after>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// socket_base.cpp
//
// Identification: src/wire/socket_base.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "wire/socket_base.h"
#include "wire/wire.h"
#include "common/exception.h"

#include <sys/un.h>
#include <string>

namespace peloton {
namespace wire {

template <typename B>
bool SocketManager<B>::RefillReadBuffer() {
  ssize_t bytes_read;

  // our buffer is to be emptied
  rbuf.Reset();

  // return explicitly
  for (;;) {
    //  try to fill the available space in the buffer
    bytes_read = read(sock_fd, &rbuf.buf[rbuf.buf_ptr],
                      SOCKET_BUFFER_SIZE - rbuf.buf_size);

    if (bytes_read < 0) {
		// Some other error occurred, close the socket, remove
		// the event and free the client structure.
    	switch(errno) {
		  case EINTR:
			  continue;
			  break;
		  case EAGAIN:
			  LOG_INFO("Error Reading: EAGAIN");
			  break;
		  case EBADF:
			  LOG_INFO("Error Reading: EBADF");
			  break;
		  case EDESTADDRREQ:
			  LOG_INFO("Error Reading: EDESTADDRREQ");
			  break;
		  case EDQUOT:
			  LOG_INFO("Error Reading: EDQUOT");
			  break;
		  case EFAULT:
			  LOG_INFO("Error Reading: EFAULT");
			  break;
		  case EFBIG:
			  LOG_INFO("Error Reading: EFBIG");
			  break;
		  case EINVAL:
			  LOG_INFO("Error Reading: EINVAL");
			  break;
		  case EIO:
			  LOG_INFO("Error Reading: EIO");
			  break;
		  case ENOSPC:
			  LOG_INFO("Error Reading: ENOSPC");
			  break;
		  case EPIPE:
			  LOG_INFO("Error Reading: EPIPE");
			  break;
		  default:
			  LOG_INFO("Error Reading: UNKNOWN");
		  }
      return false;
    }

    if (bytes_read == 0) {
	  // If the length of bytes returned by read is 0, this means
	  // that the client disconnected, remove the read event and the
	  // free the client structure.
      return false;
    }

    // read success, update buffer size
    rbuf.buf_size += bytes_read;

    // reset buffer ptr, to cover special case
    rbuf.buf_ptr = 0;
    return true;
  }
}

template <typename B>
bool SocketManager<B>::FlushWriteBuffer() {
  fd_set rset;
  struct timeval timeout;
  ssize_t written_bytes = 0;
  wbuf.buf_ptr = 0;
  // still outstanding bytes
  while ((int)wbuf.buf_size - written_bytes > 0) {
	  while(written_bytes <= 0){
			written_bytes = write(sock_fd, &wbuf.buf[wbuf.buf_ptr], wbuf.buf_size);
			if (written_bytes < 0) {
			  switch(errno) {
			  case EINTR:
				  continue;
				  break;
			  case EAGAIN:
				  LOG_INFO("Error Writing: EAGAIN");
				  break;
			  case EBADF:
				  LOG_INFO("Error Writing: EBADF");
				  break;
			  case EDESTADDRREQ:
				  LOG_INFO("Error Writing: EDESTADDRREQ");
				  break;
			  case EDQUOT:
				  LOG_INFO("Error Writing: EDQUOT");
				  break;
			  case EFAULT:
				  LOG_INFO("Error Writing: EFAULT");
				  break;
			  case EFBIG:
				  LOG_INFO("Error Writing: EFBIG");
				  break;
			  case EINVAL:
				  LOG_INFO("Error Writing: EINVAL");
				  break;
			  case EIO:
				  LOG_INFO("Error Writing: EIO");
				  break;
			  case ENOSPC:
				  LOG_INFO("Error Writing: ENOSPC");
				  break;
			  case EPIPE:
				  LOG_INFO("Error Writing: EPIPE");
				  break;
			  default:
				  LOG_INFO("Error Writing: UNKNOWN");
			  }
			  if (errno == EINTR) {
				// interrupts are ok, try again
				written_bytes = 0;
				continue;
			  } else if (errno == EAGAIN) {
				  FD_ZERO (&rset);
				  FD_SET (sock_fd, &rset);
				  timeout.tv_sec = 5;
				  written_bytes = select(sock_fd + 1, &rset, NULL, NULL, &timeout);
				  if (written_bytes < 0) {
					  LOG_INFO("written_bytes < 0 after select. Fatal");
					  exit(EXIT_FAILURE);
				  } else if (written_bytes == 0) {
					  // timed out without writing any data
					  LOG_INFO("Timeout without writing");
				  }
				  // else, socket is now readable, so loop back up and do the read() again
				  written_bytes = 0;
				  continue;
			  }
			  else {
				// fatal errors
				return false;
			  }
			}

			// weird edge case?
			if (written_bytes == 0 && wbuf.buf_size != 0) {
				LOG_INFO("Not all data is written");
			  // fatal
			  return false;
			}
	  }

    // update bookkeping
    wbuf.buf_ptr += written_bytes;
    wbuf.buf_size -= written_bytes;
  }

  // buffer is empty
  wbuf.Reset();

  // we are ok
  return true;
}

template <typename B>
bool SocketManager<B>::CanRead() {
  // Size of header (msg type + size)
  uint32_t header_size = sizeof(int32_t) + 1;
  uint32_t pkt_size = 0;
  // Size of available data for read
  size_t window = rbuf.buf_size - rbuf.buf_ptr;
  // If can read header
  if(header_size <= window) {
    PktBuf dummy_pkt;
	// Read the header size
	dummy_pkt.insert(std::end(dummy_pkt), std::begin(rbuf.buf) + rbuf.buf_ptr,
            std::begin(rbuf.buf) + rbuf.buf_ptr + header_size);
	// Get size of message
	std::copy(dummy_pkt.begin() + 1, dummy_pkt.end(),
	        reinterpret_cast<uchar *>(&pkt_size));
	pkt_size = ntohl(pkt_size) - sizeof(int32_t);
	// If header and size is larger than window, don't read untill receive a
	// read callback and buffer is refilled
	if(header_size + pkt_size > window) {
	  	return false;
	}
  }
  else {
	return false;
  }
  return true;
}

/*
 * read - Tries to read "bytes" bytes into packet's buffer. Returns true on
 * success.
 * 		false on failure. B can be any STL container.
 */
template <typename B>
bool SocketManager<B>::ReadBytes(B &pkt_buf, size_t bytes) {
  size_t window, pkt_buf_idx = 0;
  // while data still needs to be read
  while (bytes) {
    // how much data is available
    window = rbuf.buf_size - rbuf.buf_ptr;
    if (bytes <= window) {
      pkt_buf.insert(std::end(pkt_buf), std::begin(rbuf.buf) + rbuf.buf_ptr,
                     std::begin(rbuf.buf) + rbuf.buf_ptr + bytes);

      // move the pointer
      rbuf.buf_ptr += bytes;

      // move pkt_buf_idx as well
      pkt_buf_idx += bytes;

      return true;
    } else {
      // read what is available for non-trivial window
      if (window > 0) {
        pkt_buf.insert(std::end(pkt_buf), std::begin(rbuf.buf) + rbuf.buf_ptr,
                       std::begin(rbuf.buf) + rbuf.buf_size);

        // update bytes leftover
        bytes -= window;

        // update pkt_buf_idx
        pkt_buf_idx += window;
      }

      // refill buffer, reset buf ptr here
      if (!RefillReadBuffer()) {
        // nothing more to read, end
        return false;
      }
    }
  }

  return true;
}

template <typename B>
void SocketManager<B>::PrintWriteBuffer() {
	std::cout << "Write Buffer:" << std::endl;
	for(int i = 0; i < wbuf.buf_size; ++i) {
		std::cout << wbuf.buf[i] << " ";
	}
	std::cout << std::endl;
}

template <typename B>
bool SocketManager<B>::BufferWriteBytes(B &pkt_buf, size_t len, uchar type) {
  size_t window, pkt_buf_ptr = 0;
  int len_nb;  // length in network byte order

  // check if we don't have enough space in the buffer
  if (wbuf.GetMaxSize() - wbuf.buf_ptr < 1 + sizeof(int32_t)) {
    // buffer needs to be flushed before adding header
	  std::cout << "FlushWriteBuffer due to not enough space" << std::endl;
	  PrintWriteBuffer();
    FlushWriteBuffer();
  }

  // assuming wbuf is now large enough to
  // fit type and size fields in one go
  if (type != 0) {
    // type shouldn't be ignored
    wbuf.buf[wbuf.buf_ptr++] = type;
  }

  // make len include its field size as well
  len_nb = htonl(len + sizeof(int32_t));

  // append the bytes of this integer in network-byte order
  std::copy(reinterpret_cast<uchar *>(&len_nb),
            reinterpret_cast<uchar *>(&len_nb) + 4,
            std::begin(wbuf.buf) + wbuf.buf_ptr);

  // move the write buffer pointer and update size of the socket buffer
  wbuf.buf_ptr += sizeof(int32_t);
  wbuf.buf_size = wbuf.buf_ptr;

  // fill the contents
  while (len) {
    window = wbuf.GetMaxSize() - wbuf.buf_ptr;
    if (len <= window) {
      // contents fit in the window, range copy "len" bytes
      std::copy(std::begin(pkt_buf) + pkt_buf_ptr,
                std::begin(pkt_buf) + pkt_buf_ptr + len,
                std::begin(wbuf.buf) + wbuf.buf_ptr);

      // Move the cursor and update size of socket buffer
      wbuf.buf_ptr += len;
      wbuf.buf_size = wbuf.buf_ptr;
      std::cout << "Filled the write buffer but not flushed yet" << std::endl;
      PrintWriteBuffer();
      return true;
    } else {
    	std::cout << "available window (" << window <<  ") is less than the length (" << len << ")" << std::endl;
        /* contents longer than socket buffer size, fill up the socket buffer
         *  with "window" bytes
         */
        std::copy(std::begin(pkt_buf) + pkt_buf_ptr,
                std::begin(pkt_buf) + pkt_buf_ptr + window,
                std::begin(wbuf.buf) + wbuf.buf_ptr);

        // move the packet's cursor
        pkt_buf_ptr += window;
        len -= window;

        wbuf.buf_size = wbuf.GetMaxSize();

        std::cout << "Before flushing write buffer..." << std::endl;
        PrintWriteBuffer();
        // write failure
        if (!FlushWriteBuffer()) {
          std::cout << "Failed to flush write buffer" << std::endl;
    	  return false;
        }
        else {
          std::cout << "Flushed write buffer successfully" << std::endl;
        }
    }
  }
  return true;
}

template <typename B>
void SocketManager<B>::CloseSocket() {
  for (;;) {
    int status = close(sock_fd);
    if (status < 0) {
      // failed close
      if (errno == EINTR) {
        // interrupted, try closing again
        continue;
      }
    }
    return;
  }
}

// explicit template instantiation for read_bytes
template class SocketManager<PktBuf>;

}  // End wire namespace
}  // End peloton namespace
<|endoftext|>


<commit_before>#include <unordered_map>
#include <iostream>
#include <fstream>
#include <pvm3.h>
#include <mcheck.h>
#include "consts.h"

using namespace std;

unordered_map<string,int> frequency_list;
unordered_map<string,string> tree_list;

void read_frequency_list(string filename)
{
  ifstream in;
  in.open(filename.c_str());
  string word;
  int count;
  while (in >> word >> count)
    {
      frequency_list[word] = count;
    }
}
int main(int argc, char ** argv)
{
  mtrace();
  ofstream log;
  log.open("/tmp/silben-master.log");
  int sbuf = pvm_initsend(PvmDataDefault);
  log << "read frequency list" << endl;
  read_frequency_list(WORD_FREQ_LIST);
  log << "finished reading" << endl;
  log << "spawning threads" << endl;
  int host_count;
  pvm_config(&host_count,NULL,NULL);
  int task_count=host_count*PER_HOST_TASK_COUNT;
  // Task-IDs
  int tids[task_count];
  int r=pvm_spawn((char *)"silben_slave",NULL,PvmTaskDefault,NULL,task_count,tids);
  if (r<task_count)
  {
    for(int ct=0;ct<task_count;ct++)
      printf("Spawn error %d\n",tids[ct]);
  }
  log << "finished spawning" << endl;
  unordered_map<string,int>::iterator it = frequency_list.begin();
  char *word = (char *) malloc(48);
  char *tree = (char *) malloc(2048);
  log << "looping" << endl;
  while (it != frequency_list.end())
    {
      // See if DATA is pending
      if (pvm_probe(-1,DATA))
	{
	  int recbuf=pvm_recv(-1,DATA);
	  log << "got DATA" << endl;
	  for (int ct = 0; ct < BLOCK_SIZE; ct++)
	    {
	      pvm_upkstr(word);
	      pvm_upkstr(tree);
	      tree_list[string(word)] = string(tree);
	    }
	}
      // Wait for a NEXT request
      int recbuf=pvm_recv(-1,NEXT);
      log << "got NEXT" << endl;
      int tid;
      pvm_bufinfo(recbuf,NULL,NULL,&tid);
      pvm_initsend(PvmDataDefault);
      for (int ct = 0; ct < BLOCK_SIZE; ct++)
	{
	  if (it != frequency_list.end())
	    {
	      log << "Pack " << it->first << endl;
	      pvm_pkstr((char *)it->first.c_str());
	      it++;
	    }
	  else
	    break;
	}
      int sbuf = pvm_send(tid,DATA);
      log << "send DATA with " << sbuf << endl;
    }
  log << "Exiting" << endl;
  free(word);
  free(tree);
  log.close();
  muntrace();
}
<commit_msg>Removed mtrace<commit_after>#include <unordered_map>
#include <iostream>
#include <fstream>
#include <pvm3.h>
#include <mcheck.h>
#include "consts.h"

using namespace std;

unordered_map<string,int> frequency_list;
unordered_map<string,string> tree_list;

void read_frequency_list(string filename)
{
  ifstream in;
  in.open(filename.c_str());
  string word;
  int count;
  while (in >> word >> count)
    {
      frequency_list[word] = count;
    }
}
int main(int argc, char ** argv)
{
  ofstream log;
  log.open("/tmp/silben-master.log");
  int sbuf = pvm_initsend(PvmDataDefault);
  log << "read frequency list" << endl;
  read_frequency_list(WORD_FREQ_LIST);
  log << "finished reading" << endl;
  log << "spawning threads" << endl;
  int host_count;
  pvm_config(&host_count,NULL,NULL);
  int task_count=host_count*PER_HOST_TASK_COUNT;
  // Task-IDs
  int tids[task_count];
  int r=pvm_spawn((char *)"silben_slave",NULL,PvmTaskDefault,NULL,task_count,tids);
  if (r<task_count)
  {
    for(int ct=0;ct<task_count;ct++)
      printf("Spawn error %d\n",tids[ct]);
  }
  log << "finished spawning" << endl;
  unordered_map<string,int>::iterator it = frequency_list.begin();
  char *word = (char *) malloc(48);
  char *tree = (char *) malloc(2048);
  log << "looping" << endl;
  while (it != frequency_list.end())
    {
      // See if DATA is pending
      if (pvm_probe(-1,DATA))
	{
	  int recbuf=pvm_recv(-1,DATA);
	  log << "got DATA" << endl;
	  for (int ct = 0; ct < BLOCK_SIZE; ct++)
	    {
	      pvm_upkstr(word);
	      pvm_upkstr(tree);
	      log << "Unpacked " << word << " and " << tree << endl;
	      tree_list[string(word)] = string(tree);
	    }
	}
      // Wait for a NEXT request
      int recbuf=pvm_recv(-1,NEXT);
      log << "got NEXT" << endl;
      int tid;
      pvm_bufinfo(recbuf,NULL,NULL,&tid);
      pvm_initsend(PvmDataDefault);
      for (int ct = 0; ct < BLOCK_SIZE; ct++)
	{
	  if (it != frequency_list.end())
	    {
	      log << "Pack " << it->first << endl;
	      pvm_pkstr((char *)it->first.c_str());
	      it++;
	    }
	  else
	    break;
	}
      int sbuf = pvm_send(tid,DATA);
      log << "send DATA with " << sbuf << endl;
    }
  log << "Exiting" << endl;
  free(word);
  free(tree);
  log.close();
}
<|endoftext|>


<commit_before>/*
 * Agora.cpp
 *
 *  Created on: May 18, 2014
 *      Author: Flix Robles felrobelv at gmail dot com
 * Loosely based on Agora Voting:
 * https://github.com/agoraciudadana/agora-ciudadana/blob/security/agora_site/static/js/agora/views/voting_booth.js
 */

#include "Agora.h"

Agora::Encrypted_answer::Encrypted_answer()
{
	mpz_init(alpha);
	mpz_init(beta);
	mpz_init(challenge);
	mpz_init(response);
}

Agora::Encrypted_answer::Encrypted_answer(const mpz_t &alpha, const mpz_t &beta, const ElGamal::PlaintextCommitment &commitment,
				const mpz_t &challenge,const mpz_t &response)
{
	this->commitment = commitment;
	mpz_init_set(this->alpha, alpha);
	mpz_init_set(this->beta, beta);
	mpz_init_set(this->challenge, challenge);
	mpz_init_set(this->response, response);
}

Agora::Encrypted_answer Agora::encryptAnswer(const ElGamal::PublicKey &pk, const mpz_t &encoded_answer, const mpz_t &randomness) {
	/**
	 * Here we not only just encrypt the answer but also provide a
	 * verifiable Proof of Knowledge (PoK) of the plaintext, using the
	 * Schnorr Protocol with Fiat-Shamir (which is a method of
	 * converting an interactive PoK into non interactive using a hash
	 * that substitutes the random oracle). We use sha256 for hashing.
	 */
	Agora::Encrypted_answer answer;
	bool b = true;
	ElGamal::Plaintext plaintext = ElGamal::Plaintext(encoded_answer, pk, b);
	mpz_t zero, random;
	mpz_init(zero);
	mpz_init(random);
	//returns 0 only if randomness == 0
	if (0 == mpz_cmp(randomness,zero)) 	{
		Random::getRandomInteger(random, pk.q);
	} else if (mpz_cmp(randomness,pk.q) > 0 ) { //randomness is too big
		mpz_mod(random, randomness, pk.q);
	}
	else {
		mpz_set(random, randomness);
	}
	ElGamal::Ciphertext ciphertext = ElGamal::encrypt(pk, plaintext, random);
	ElGamal::Fiatshamir_dlog_challenge_generator generator;
	ElGamal::DLogProof proof = plaintext.proveKnowledge(ciphertext.alpha, random, generator);
	answer = Agora::Encrypted_answer(ciphertext.alpha, ciphertext.beta, proof.commitment, proof.response, proof.challenge);
	return answer;
}
<commit_msg>Add decryption sugar to Agora source<commit_after>/*
 * Agora.cpp
 *
 *  Created on: May 18, 2014
 *      Author: F�lix Robles felrobelv at gmail dot com
 * Loosely based on Agora Voting:
 * https://github.com/agoraciudadana/agora-ciudadana/blob/security/agora_site/static/js/agora/views/voting_booth.js
 */

#include "Agora.h"

Agora::Encrypted_answer::Encrypted_answer()
{
	mpz_init(alpha);
	mpz_init(beta);
	mpz_init(challenge);
	mpz_init(response);
}

Agora::Encrypted_answer::Encrypted_answer(const mpz_t &alpha, const mpz_t &beta, const ElGamal::PlaintextCommitment &commitment,
				const mpz_t &challenge,const mpz_t &response)
{
	this->commitment = commitment;
	mpz_init_set(this->alpha, alpha);
	mpz_init_set(this->beta, beta);
	mpz_init_set(this->challenge, challenge);
	mpz_init_set(this->response, response);
}

Agora::Encrypted_answer Agora::encryptAnswer(const ElGamal::PublicKey &pk, const mpz_t &encoded_answer, const mpz_t &randomness) {
	/**
	 * Here we not only just encrypt the answer but also provide a
	 * verifiable Proof of Knowledge (PoK) of the plaintext, using the
	 * Schnorr Protocol with Fiat-Shamir (which is a method of
	 * converting an interactive PoK into non interactive using a hash
	 * that substitutes the random oracle). We use sha256 for hashing.
	 */
	Agora::Encrypted_answer answer;
	bool b = true;
	ElGamal::Plaintext plaintext = ElGamal::Plaintext(encoded_answer, pk, b);
	mpz_t zero, random;
	mpz_init(zero);
	mpz_init(random);
	//returns 0 only if randomness == 0
	if (0 == mpz_cmp(randomness,zero)) 	{
		Random::getRandomInteger(random, pk.q);
	} else if (mpz_cmp(randomness,pk.q) > 0 ) { //randomness is too big
		mpz_mod(random, randomness, pk.q);
	}
	else {
		mpz_set(random, randomness);
	}
	ElGamal::Ciphertext ciphertext = ElGamal::encrypt(pk, plaintext, random);
	ElGamal::Fiatshamir_dlog_challenge_generator generator;
	ElGamal::DLogProof proof = plaintext.proveKnowledge(ciphertext.alpha, random, generator);
	answer = Agora::Encrypted_answer(ciphertext.alpha, ciphertext.beta, proof.commitment, proof.response, proof.challenge);
	return answer;
}

ElGamal::Plaintext Agora::decryptAnswer(const SecretKey &sk, const Encrypted_answer & encryptedanswer) {
  ElGamal::Ciphertext ciphertext(encryptedanswer.alpha, encryptedanswer.beta, sk.pk);
  ElGamal::Plaintext cleartext = ElGamal::decrypt(sk, ciphertext);
  return cleartext;
}
<|endoftext|>


<commit_before>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2014 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "xenia/base/string.h"

// codecvt existence check
#ifdef __clang__
// using clang
#if (__clang_major__ < 4)  // 3.3 has it but I think we need at least 4 anyway
// insufficient clang version
#define NO_CODECVT 1
#else
#include <codecvt>
#endif
#elif defined(__GNUC__) || defined(__GNUG__)
// using gcc
#if (__GNUC__ < 5)
// insufficient clang version
#define NO_CODECVT 1
#else
#include <codecvt>
#endif
// since the windows 10 sdk is required, this shouldn't be an issue
#elif defined(_MSC_VER)
#include <codecvt>
#endif

#include <cctype>
#include <cstring>
#include <locale>

namespace xe {

std::string to_string(const std::wstring& source) {
#if NO_CODECVT
  return std::string(source.begin(), source.end());
#else
  static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
  return converter.to_bytes(source);
#endif  // XE_PLATFORM_LINUX
}

std::wstring to_wstring(const std::string& source) {
#if NO_CODECVT
  return std::wstring(source.begin(), source.end());
#else
  static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
  return converter.from_bytes(source);
#endif  // XE_PLATFORM_LINUX
}

std::string format_string(const char* format, va_list args) {
  if (!format) {
    return "";
  }
  size_t max_len = 64;
  std::string new_s;
  while (true) {
    new_s.resize(max_len);
    int ret =
        std::vsnprintf(const_cast<char*>(new_s.data()), max_len, format, args);
    if (ret > max_len) {
      // Needed size is known (+2 for termination and avoid ambiguity).
      max_len = ret + 2;
    } else if (ret == -1 || ret >= max_len - 1) {
      // Handle some buggy vsnprintf implementations.
      max_len *= 2;
    } else {
      // Everything fit for sure.
      new_s.resize(ret);
      return new_s;
    }
  }
}

std::wstring format_string(const wchar_t* format, va_list args) {
  if (!format) {
    return L"";
  }
  size_t max_len = 64;
  std::wstring new_s;
  while (true) {
    new_s.resize(max_len);
    int ret = std::vswprintf(const_cast<wchar_t*>(new_s.data()), max_len,
                             format, args);
    if (ret > max_len) {
      // Needed size is known (+2 for termination and avoid ambiguity).
      max_len = ret + 2;
    } else if (ret == -1 || ret >= max_len - 1) {
      // Handle some buggy vsnprintf implementations.
      max_len *= 2;
    } else {
      // Everything fit for sure.
      new_s.resize(ret);
      return new_s;
    }
  }
}

std::vector<std::string> split_string(const std::string& path,
                                      const std::string& delimiters) {
  std::vector<std::string> parts;
  size_t n = 0;
  size_t last = 0;
  while ((n = path.find_first_of(delimiters, last)) != path.npos) {
    if (last != n) {
      parts.push_back(path.substr(last, n - last));
    }
    last = n + 1;
  }
  if (last != path.size()) {
    parts.push_back(path.substr(last));
  }
  return parts;
}

std::vector<std::wstring> split_string(const std::wstring& path,
                                       const std::wstring& delimiters) {
  std::vector<std::wstring> parts;
  size_t n = 0;
  size_t last = 0;
  while ((n = path.find_first_of(delimiters, last)) != path.npos) {
    if (last != n) {
      parts.push_back(path.substr(last, n - last));
    }
    last = n + 1;
  }
  if (last != path.size()) {
    parts.push_back(path.substr(last));
  }
  return parts;
}

std::string::size_type find_first_of_case(const std::string& target,
                                          const std::string& search) {
  const char* str = target.c_str();
  while (*str) {
    if (!strncasecmp(str, search.c_str(), search.size())) {
      break;
    }
    str++;
  }
  if (*str) {
    return str - target.c_str();
  } else {
    return std::string::npos;
  }
}

std::wstring to_absolute_path(const std::wstring& path) {
#if XE_PLATFORM_WIN32
  wchar_t buffer[kMaxPath];
  _wfullpath(buffer, path.c_str(), sizeof(buffer) / sizeof(wchar_t));
  return buffer;
#else
  char buffer[kMaxPath];
  realpath(xe::to_string(path).c_str(), buffer);
  return xe::to_wstring(buffer);
#endif  // XE_PLATFORM_WIN32
}

std::vector<std::string> split_path(const std::string& path) {
  return split_string(path, "\\/");
}

std::vector<std::wstring> split_path(const std::wstring& path) {
  return split_string(path, L"\\/");
}

std::string join_paths(const std::string& left, const std::string& right,
                       char sep) {
  if (!left.size()) {
    return right;
  } else if (!right.size()) {
    return left;
  }
  if (left[left.size() - 1] == sep) {
    return left + right;
  } else {
    return left + sep + right;
  }
}

std::wstring join_paths(const std::wstring& left, const std::wstring& right,
                        wchar_t sep) {
  if (!left.size()) {
    return right;
  } else if (!right.size()) {
    return left;
  }
  if (left[left.size() - 1] == sep) {
    return left + right;
  } else {
    return left + sep + right;
  }
}

std::wstring fix_path_separators(const std::wstring& source, wchar_t new_sep) {
  // Swap all separators to new_sep.
  wchar_t old_sep = new_sep == '\\' ? '/' : '\\';
  std::wstring::size_type pos = 0;
  std::wstring dest = source;
  while ((pos = source.find_first_of(old_sep, pos)) != std::wstring::npos) {
    dest[pos] = new_sep;
    ++pos;
  }
  // Replace redundant separators.
  pos = 0;
  while ((pos = dest.find_first_of(new_sep, pos)) != std::wstring::npos) {
    if (pos < dest.size() - 1) {
      if (dest[pos + 1] == new_sep) {
        dest.erase(pos + 1, 1);
      }
    }
    ++pos;
  }
  return dest;
}

std::string fix_path_separators(const std::string& source, char new_sep) {
  // Swap all separators to new_sep.
  char old_sep = new_sep == '\\' ? '/' : '\\';
  std::string::size_type pos = 0;
  std::string dest = source;
  while ((pos = source.find_first_of(old_sep, pos)) != std::string::npos) {
    dest[pos] = new_sep;
    ++pos;
  }
  // Replace redundant separators.
  pos = 0;
  while ((pos = dest.find_first_of(new_sep, pos)) != std::string::npos) {
    if (pos < dest.size() - 1) {
      if (dest[pos + 1] == new_sep) {
        dest.erase(pos + 1, 1);
      }
    }
    ++pos;
  }
  return dest;
}

std::string find_name_from_path(const std::string& path, char sep) {
  std::string name(path);
  if (!path.empty()) {
    std::string::size_type from(std::string::npos);
    if (path.back() == sep) {
      from = path.size() - 2;
    }
    auto pos(path.find_last_of(sep, from));
    if (pos != std::string::npos) {
      if (from == std::string::npos) {
        name = path.substr(pos + 1);
      } else {
        auto len(from - pos);
        name = path.substr(pos + 1, len);
      }
    }
  }
  return name;
}

std::wstring find_name_from_path(const std::wstring& path, wchar_t sep) {
  std::wstring name(path);
  if (!path.empty()) {
    std::wstring::size_type from(std::wstring::npos);
    if (path.back() == sep) {
      from = path.size() - 2;
    }
    auto pos(path.find_last_of(sep, from));
    if (pos != std::wstring::npos) {
      if (from == std::wstring::npos) {
        name = path.substr(pos + 1);
      } else {
        auto len(from - pos);
        name = path.substr(pos + 1, len);
      }
    }
  }
  return name;
}

std::string find_base_path(const std::string& path, char sep) {
  auto last_slash = path.find_last_of(sep);
  if (last_slash == std::string::npos) {
    return "";
  } else if (last_slash == path.length() - 1) {
    auto prev_slash = path.find_last_of(sep, last_slash - 1);
    if (prev_slash == std::string::npos) {
      return "";
    } else {
      return path.substr(0, prev_slash + 1);
    }
  } else {
    return path.substr(0, last_slash + 1);
  }
}

std::wstring find_base_path(const std::wstring& path, wchar_t sep) {
  auto last_slash = path.find_last_of(sep);
  if (last_slash == std::wstring::npos) {
    return L"";
  } else if (last_slash == path.length() - 1) {
    auto prev_slash = path.find_last_of(sep, last_slash - 1);
    if (prev_slash == std::wstring::npos) {
      return L"";
    } else {
      return path.substr(0, prev_slash + 1);
    }
  } else {
    return path.substr(0, last_slash + 1);
  }
}

int fuzzy_match(const std::string& pattern, const char* value) {
  // https://github.com/mattyork/fuzzy/blob/master/lib/fuzzy.js
  // TODO(benvanik): look at https://github.com/atom/fuzzaldrin/tree/master/src
  // This does not weight complete substrings or prefixes right, which
  // kind of sucks.
  size_t pattern_index = 0;
  size_t value_length = std::strlen(value);
  int total_score = 0;
  int local_score = 0;
  for (size_t i = 0; i < value_length; ++i) {
    if (std::tolower(value[i]) == std::tolower(pattern[pattern_index])) {
      ++pattern_index;
      local_score += 1 + local_score;
    } else {
      local_score = 0;
    }
    total_score += local_score;
  }
  return total_score;
}

std::vector<std::pair<size_t, int>> fuzzy_filter(const std::string& pattern,
                                                 const void* const* entries,
                                                 size_t entry_count,
                                                 size_t string_offset) {
  std::vector<std::pair<size_t, int>> results;
  results.reserve(entry_count);
  for (size_t i = 0; i < entry_count; ++i) {
    auto entry_value =
        reinterpret_cast<const char*>(entries[i]) + string_offset;
    int score = fuzzy_match(pattern, entry_value);
    results.emplace_back(i, score);
  }
  return results;
}

}  // namespace xe
<commit_msg>[Base] Remove MAX_PATH limit from to_absolute_path<commit_after>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2014 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include "xenia/base/string.h"

// codecvt existence check
#ifdef __clang__
// using clang
#if (__clang_major__ < 4)  // 3.3 has it but I think we need at least 4 anyway
// insufficient clang version
#define NO_CODECVT 1
#else
#include <codecvt>
#endif
#elif defined(__GNUC__) || defined(__GNUG__)
// using gcc
#if (__GNUC__ < 5)
// insufficient clang version
#define NO_CODECVT 1
#else
#include <codecvt>
#endif
// since the windows 10 sdk is required, this shouldn't be an issue
#elif defined(_MSC_VER)
#include <codecvt>
#endif

#include <cctype>
#include <cstring>
#include <locale>

namespace xe {

std::string to_string(const std::wstring& source) {
#if NO_CODECVT
  return std::string(source.begin(), source.end());
#else
  static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
  return converter.to_bytes(source);
#endif  // XE_PLATFORM_LINUX
}

std::wstring to_wstring(const std::string& source) {
#if NO_CODECVT
  return std::wstring(source.begin(), source.end());
#else
  static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
  return converter.from_bytes(source);
#endif  // XE_PLATFORM_LINUX
}

std::string format_string(const char* format, va_list args) {
  if (!format) {
    return "";
  }
  size_t max_len = 64;
  std::string new_s;
  while (true) {
    new_s.resize(max_len);
    int ret =
        std::vsnprintf(const_cast<char*>(new_s.data()), max_len, format, args);
    if (ret > max_len) {
      // Needed size is known (+2 for termination and avoid ambiguity).
      max_len = ret + 2;
    } else if (ret == -1 || ret >= max_len - 1) {
      // Handle some buggy vsnprintf implementations.
      max_len *= 2;
    } else {
      // Everything fit for sure.
      new_s.resize(ret);
      return new_s;
    }
  }
}

std::wstring format_string(const wchar_t* format, va_list args) {
  if (!format) {
    return L"";
  }
  size_t max_len = 64;
  std::wstring new_s;
  while (true) {
    new_s.resize(max_len);
    int ret = std::vswprintf(const_cast<wchar_t*>(new_s.data()), max_len,
                             format, args);
    if (ret > max_len) {
      // Needed size is known (+2 for termination and avoid ambiguity).
      max_len = ret + 2;
    } else if (ret == -1 || ret >= max_len - 1) {
      // Handle some buggy vsnprintf implementations.
      max_len *= 2;
    } else {
      // Everything fit for sure.
      new_s.resize(ret);
      return new_s;
    }
  }
}

std::vector<std::string> split_string(const std::string& path,
                                      const std::string& delimiters) {
  std::vector<std::string> parts;
  size_t n = 0;
  size_t last = 0;
  while ((n = path.find_first_of(delimiters, last)) != path.npos) {
    if (last != n) {
      parts.push_back(path.substr(last, n - last));
    }
    last = n + 1;
  }
  if (last != path.size()) {
    parts.push_back(path.substr(last));
  }
  return parts;
}

std::vector<std::wstring> split_string(const std::wstring& path,
                                       const std::wstring& delimiters) {
  std::vector<std::wstring> parts;
  size_t n = 0;
  size_t last = 0;
  while ((n = path.find_first_of(delimiters, last)) != path.npos) {
    if (last != n) {
      parts.push_back(path.substr(last, n - last));
    }
    last = n + 1;
  }
  if (last != path.size()) {
    parts.push_back(path.substr(last));
  }
  return parts;
}

std::string::size_type find_first_of_case(const std::string& target,
                                          const std::string& search) {
  const char* str = target.c_str();
  while (*str) {
    if (!strncasecmp(str, search.c_str(), search.size())) {
      break;
    }
    str++;
  }
  if (*str) {
    return str - target.c_str();
  } else {
    return std::string::npos;
  }
}

std::wstring to_absolute_path(const std::wstring& path) {
#if XE_PLATFORM_WIN32
  std::wstring result;
  wchar_t* buffer = _wfullpath(nullptr, path.c_str(), 0);
  if (buffer != nullptr) {
    result.assign(buffer);
    free(buffer);
  }
  return result;
#else
  char buffer[kMaxPath];
  realpath(xe::to_string(path).c_str(), buffer);
  return xe::to_wstring(buffer);
#endif  // XE_PLATFORM_WIN32
}

std::vector<std::string> split_path(const std::string& path) {
  return split_string(path, "\\/");
}

std::vector<std::wstring> split_path(const std::wstring& path) {
  return split_string(path, L"\\/");
}

std::string join_paths(const std::string& left, const std::string& right,
                       char sep) {
  if (!left.size()) {
    return right;
  } else if (!right.size()) {
    return left;
  }
  if (left[left.size() - 1] == sep) {
    return left + right;
  } else {
    return left + sep + right;
  }
}

std::wstring join_paths(const std::wstring& left, const std::wstring& right,
                        wchar_t sep) {
  if (!left.size()) {
    return right;
  } else if (!right.size()) {
    return left;
  }
  if (left[left.size() - 1] == sep) {
    return left + right;
  } else {
    return left + sep + right;
  }
}

std::wstring fix_path_separators(const std::wstring& source, wchar_t new_sep) {
  // Swap all separators to new_sep.
  wchar_t old_sep = new_sep == '\\' ? '/' : '\\';
  std::wstring::size_type pos = 0;
  std::wstring dest = source;
  while ((pos = source.find_first_of(old_sep, pos)) != std::wstring::npos) {
    dest[pos] = new_sep;
    ++pos;
  }
  // Replace redundant separators.
  pos = 0;
  while ((pos = dest.find_first_of(new_sep, pos)) != std::wstring::npos) {
    if (pos < dest.size() - 1) {
      if (dest[pos + 1] == new_sep) {
        dest.erase(pos + 1, 1);
      }
    }
    ++pos;
  }
  return dest;
}

std::string fix_path_separators(const std::string& source, char new_sep) {
  // Swap all separators to new_sep.
  char old_sep = new_sep == '\\' ? '/' : '\\';
  std::string::size_type pos = 0;
  std::string dest = source;
  while ((pos = source.find_first_of(old_sep, pos)) != std::string::npos) {
    dest[pos] = new_sep;
    ++pos;
  }
  // Replace redundant separators.
  pos = 0;
  while ((pos = dest.find_first_of(new_sep, pos)) != std::string::npos) {
    if (pos < dest.size() - 1) {
      if (dest[pos + 1] == new_sep) {
        dest.erase(pos + 1, 1);
      }
    }
    ++pos;
  }
  return dest;
}

std::string find_name_from_path(const std::string& path, char sep) {
  std::string name(path);
  if (!path.empty()) {
    std::string::size_type from(std::string::npos);
    if (path.back() == sep) {
      from = path.size() - 2;
    }
    auto pos(path.find_last_of(sep, from));
    if (pos != std::string::npos) {
      if (from == std::string::npos) {
        name = path.substr(pos + 1);
      } else {
        auto len(from - pos);
        name = path.substr(pos + 1, len);
      }
    }
  }
  return name;
}

std::wstring find_name_from_path(const std::wstring& path, wchar_t sep) {
  std::wstring name(path);
  if (!path.empty()) {
    std::wstring::size_type from(std::wstring::npos);
    if (path.back() == sep) {
      from = path.size() - 2;
    }
    auto pos(path.find_last_of(sep, from));
    if (pos != std::wstring::npos) {
      if (from == std::wstring::npos) {
        name = path.substr(pos + 1);
      } else {
        auto len(from - pos);
        name = path.substr(pos + 1, len);
      }
    }
  }
  return name;
}

std::string find_base_path(const std::string& path, char sep) {
  auto last_slash = path.find_last_of(sep);
  if (last_slash == std::string::npos) {
    return "";
  } else if (last_slash == path.length() - 1) {
    auto prev_slash = path.find_last_of(sep, last_slash - 1);
    if (prev_slash == std::string::npos) {
      return "";
    } else {
      return path.substr(0, prev_slash + 1);
    }
  } else {
    return path.substr(0, last_slash + 1);
  }
}

std::wstring find_base_path(const std::wstring& path, wchar_t sep) {
  auto last_slash = path.find_last_of(sep);
  if (last_slash == std::wstring::npos) {
    return L"";
  } else if (last_slash == path.length() - 1) {
    auto prev_slash = path.find_last_of(sep, last_slash - 1);
    if (prev_slash == std::wstring::npos) {
      return L"";
    } else {
      return path.substr(0, prev_slash + 1);
    }
  } else {
    return path.substr(0, last_slash + 1);
  }
}

int fuzzy_match(const std::string& pattern, const char* value) {
  // https://github.com/mattyork/fuzzy/blob/master/lib/fuzzy.js
  // TODO(benvanik): look at https://github.com/atom/fuzzaldrin/tree/master/src
  // This does not weight complete substrings or prefixes right, which
  // kind of sucks.
  size_t pattern_index = 0;
  size_t value_length = std::strlen(value);
  int total_score = 0;
  int local_score = 0;
  for (size_t i = 0; i < value_length; ++i) {
    if (std::tolower(value[i]) == std::tolower(pattern[pattern_index])) {
      ++pattern_index;
      local_score += 1 + local_score;
    } else {
      local_score = 0;
    }
    total_score += local_score;
  }
  return total_score;
}

std::vector<std::pair<size_t, int>> fuzzy_filter(const std::string& pattern,
                                                 const void* const* entries,
                                                 size_t entry_count,
                                                 size_t string_offset) {
  std::vector<std::pair<size_t, int>> results;
  results.reserve(entry_count);
  for (size_t i = 0; i < entry_count; ++i) {
    auto entry_value =
        reinterpret_cast<const char*>(entries[i]) + string_offset;
    int score = fuzzy_match(pattern, entry_value);
    results.emplace_back(i, score);
  }
  return results;
}

}  // namespace xe
<|endoftext|>


<commit_before>#pragma once

#include "Features.hpp"

#include "support/disable_warnings.hpp"
#include <boost/any.hpp>
#include <boost/proto/core.hpp>
#include <boost/proto/context.hpp>
#include <boost/thread/future.hpp>
#include "support/enable_warnings.hpp"

namespace metaSMT {

  /**
   * @brief direct Solver integration
   *
   *  DirectSolver_Context takes a SolverType and directly feeds all commands
   *  to it. Variable expressions are cached and only evaluated once.
   **/
  template<typename SolverContext>
  struct UnpackFuture_Context
    : SolverContext
  {
    UnpackFuture_Context() {}

    /// The returned expression type is the result_type of the SolverContext
    typedef typename SolverContext::result_type result_type;

    template< typename T>
    result_type operator() (boost::shared_future<T> & e, boost::any const & any) {
      return e.get();
    }

    using SolverContext::command;
    using SolverContext::operator();

  };

  namespace features {
    template<typename Context, typename Feature>
    struct supports< UnpackFuture_Context<Context>, Feature>
    : supports<Context, Feature>::type {};
  }

} // namespace metaSMT

//  vim: ft=cpp:ts=2:sw=2:expandtab
<commit_msg>changed UnpackFuture_Context to take shared_futures by values<commit_after>#pragma once

#include "Features.hpp"

#include "support/disable_warnings.hpp"
#include <boost/any.hpp>
#include <boost/proto/core.hpp>
#include <boost/proto/context.hpp>
#include <boost/thread/future.hpp>
#include "support/enable_warnings.hpp"

namespace metaSMT {

  /**
   * @brief direct Solver integration
   *
   *  DirectSolver_Context takes a SolverType and directly feeds all commands
   *  to it. Variable expressions are cached and only evaluated once.
   **/
  template<typename SolverContext>
  struct UnpackFuture_Context
    : SolverContext
  {
    UnpackFuture_Context() {}

    /// The returned expression type is the result_type of the SolverContext
    typedef typename SolverContext::result_type result_type;

    result_type operator() (boost::shared_future<result_type> e, boost::any const & any) {
      return e.get();
    }

    using SolverContext::command;
    using SolverContext::operator();

  };

  namespace features {
    template<typename Context, typename Feature>
    struct supports< UnpackFuture_Context<Context>, Feature>
    : supports<Context, Feature>::type {};
  }

} // namespace metaSMT

//  vim: ft=cpp:ts=2:sw=2:expandtab
<|endoftext|>


<commit_before>#include "StdAfx.h"
#include "RawDecoder.h"
/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009 Klaus Post

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

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

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

    http://www.klauspost.com
*/

namespace RawSpeed {

RawDecoder::RawDecoder(FileMap* file) : mFile(file), mRaw(RawImage::create()) {
  decoderVersion = 0;
}

RawDecoder::~RawDecoder(void) {
  for (guint i = 0 ; i < errors.size(); i++) {
    free((void*)errors[i]);
  }
  errors.clear();
}

void RawDecoder::readUncompressedRaw(ByteStream &input, iPoint2D& size, iPoint2D& offset, int inputPitch, int bitPerPixel, gboolean MSBOrder) {
  guchar* data = mRaw->getData();
  guint outPitch = mRaw->pitch;
  guint w = size.x;
  guint h = size.y;
  guint cpp = mRaw->getCpp();

  if (input.getRemainSize() < (inputPitch*h)) {
    if ((int)input.getRemainSize() > inputPitch)
      h = input.getRemainSize() / inputPitch - 1;
    else
      ThrowIOE("readUncompressedRaw: Not enough data to decode a single line. Image file truncated.");
  }
  if (bitPerPixel > 16)
    ThrowRDE("readUncompressedRaw: Unsupported bit depth");

  guint skipBits = inputPitch - w * bitPerPixel / 8;  // Skip per line
  if (offset.y > mRaw->dim.y)
    ThrowRDE("readUncompressedRaw: Invalid y offset");
  if (offset.x + size.x > mRaw->dim.x)
    ThrowRDE("readUncompressedRaw: Invalid x offset");

  guint y = offset.y;
  h = MIN(h + (guint)offset.y, (guint)mRaw->dim.y);

  if (MSBOrder) {
    BitPumpMSB bits(&input);
    w *= cpp;
    for (; y < h; y++) {
      gushort* dest = (gushort*) & data[offset.x*sizeof(gushort)*cpp+y*outPitch];
      bits.checkPos();
      for (guint x = 0 ; x < w; x++) {
        guint b = bits.getBits(bitPerPixel);
        dest[x] = b;
      }
      bits.skipBits(skipBits);
    }

  } else {

    if (bitPerPixel == 16)  {
      BitBlt(&data[offset.x*sizeof(gushort)*cpp+y*outPitch], outPitch,
             input.getData(), inputPitch, w*mRaw->bpp, h - y);
      return;
    }
    if (bitPerPixel == 12)  {
      Decode12BitRaw(input, w, h);
      return;
    }
    BitPumpPlain bits(&input);
    w *= cpp;
    for (; y < h; y++) {
      gushort* dest = (gushort*) & data[offset.x*sizeof(gushort)+y*outPitch];
      bits.checkPos();
      for (guint x = 0 ; x < w; x++) {
        guint b = bits.getBits(bitPerPixel);
        dest[x] = b;
      }
      bits.skipBits(skipBits);
    }
  }
}

void RawDecoder::Decode12BitRaw(ByteStream &input, guint w, guint h) {
  guchar* data = mRaw->getData();
  guint pitch = mRaw->pitch;
  const guchar *in = input.getData();
  if (input.getRemainSize() < (w*h)) {
    if ((int)input.getRemainSize() > w)
      h = input.getRemainSize() / w - 1;
    else
      ThrowIOE("readUncompressedRaw: Not enough data to decode a single line. Image file truncated.");
  }
  for (guint y = 0; y < h; y++) {
    gushort* dest = (gushort*) & data[y*pitch];
    for (guint x = 0 ; x < w; x += 2) {
      guint g1 = *in++;
      guint g2 = *in++;
      dest[x] = g1 | ((g2 & 0xf) << 8);
      guint g3 = *in++;
      dest[x+1] = (g2 >> 4) | (g3 << 4);
    }
  }
}

void RawDecoder::checkCameraSupported(CameraMetaData *meta, string make, string model, string mode) {
  TrimSpaces(make);
  TrimSpaces(model);
  Camera* cam = meta->getCamera(make, model, mode);
  if (!cam) {
    if (mode.length() == 0)
      printf("Unable to find camera in database: %s %s %s\n", make.c_str(), model.c_str(), mode.c_str());

    return;    // Assume true.
  }

  if (!cam->supported)
    ThrowRDE("Camera not supported (explicit). Sorry.");

  if (cam->decoderVersion > decoderVersion)
    ThrowRDE("Camera not supported in this version. Update RawSpeed for support.");
}

void RawDecoder::setMetaData(CameraMetaData *meta, string make, string model, string mode) {
  TrimSpaces(make);
  TrimSpaces(model);
  Camera *cam = meta->getCamera(make, model, mode);
  if (!cam) {
    printf("Unable to find camera in database: %s %s %s\nPlease upload file to ftp.rawstudio.org, thanks!\n", make.c_str(), model.c_str(), mode.c_str());
    return;
  }

  iPoint2D new_size = cam->cropSize;

  // If crop size is negative, use relative cropping
  if (new_size.x <= 0)
    new_size.x = mRaw->dim.x - cam->cropPos.x + new_size.x;

  if (new_size.y <= 0)
    new_size.y = mRaw->dim.y - cam->cropPos.y + new_size.y;

  mRaw->subFrame(cam->cropPos, new_size);
  mRaw->cfa = cam->cfa;

  // Shift CFA to match crop
  if (cam->cropPos.x & 1)
    mRaw->cfa.shiftLeft();
  if (cam->cropPos.y & 1)
    mRaw->cfa.shiftDown();

  mRaw->blackLevel = cam->black;
  mRaw->whitePoint = cam->white;
}

void RawDecoder::TrimSpaces(string& str) {
  // Trim Both leading and trailing spaces
  size_t startpos = str.find_first_not_of(" \t"); // Find the first character position after excluding leading blank spaces
  size_t endpos = str.find_last_not_of(" \t"); // Find the first character position from reverse af

  // if all spaces or empty return an empty string
  if ((string::npos == startpos) || (string::npos == endpos)) {
    str = "";
  } else
    str = str.substr(startpos, endpos - startpos + 1);
}

void *RawDecoderDecodeThread(void *_this) {
  RawDecoderThread* me = (RawDecoderThread*)_this;
  try {
    me->parent->decodeThreaded(me);
  } catch (RawDecoderException ex) {
    me->error = _strdup(ex.what());
  } catch (IOException ex) {
    me->error = _strdup(ex.what());
  }

  pthread_exit(NULL);
  return 0;
}

void RawDecoder::startThreads() {
  guint threads;
#ifdef WIN32
  threads = pthread_num_processors_np();
#else
  // FIXME: Don't depend on Rawstudio.
  threads = rs_get_number_of_processor_cores();
#endif
  int y_offset = 0;
  int y_per_thread = (mRaw->dim.y + threads - 1) / threads;
  RawDecoderThread *t = new RawDecoderThread[threads];

  pthread_attr_t attr;

  /* Initialize and set thread detached attribute */
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

  for (guint i = 0; i < threads; i++) {
    t[i].start_y = y_offset;
    t[i].end_y = MIN(y_offset + y_per_thread, mRaw->dim.y);
    t[i].parent = this;
    pthread_create(&t[i].threadid, &attr, RawDecoderDecodeThread, &t[i]);
    y_offset = t[i].end_y;
  }

  void *status;
  for (guint i = 0; i < threads; i++) {
    pthread_join(t[i].threadid, &status);
    if (t[i].error) {
      errors.push_back(t[i].error);
    }
  }
  delete[] t;
}

void RawDecoder::decodeThreaded(RawDecoderThread * t) {
  ThrowRDE("Internal Error: This class does not support threaded decoding");
}

} // namespace RawSpeed<commit_msg>Raw Decoder: Ensure that input pitch == w, before using 12 bit decoder, and fix size calculation, broken in rev 227.<commit_after>#include "StdAfx.h"
#include "RawDecoder.h"
/*
    RawSpeed - RAW file decoder.

    Copyright (C) 2009 Klaus Post

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

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

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

    http://www.klauspost.com
*/

namespace RawSpeed {

RawDecoder::RawDecoder(FileMap* file) : mFile(file), mRaw(RawImage::create()) {
  decoderVersion = 0;
}

RawDecoder::~RawDecoder(void) {
  for (guint i = 0 ; i < errors.size(); i++) {
    free((void*)errors[i]);
  }
  errors.clear();
}

void RawDecoder::readUncompressedRaw(ByteStream &input, iPoint2D& size, iPoint2D& offset, int inputPitch, int bitPerPixel, gboolean MSBOrder) {
  guchar* data = mRaw->getData();
  guint outPitch = mRaw->pitch;
  guint w = size.x;
  guint h = size.y;
  guint cpp = mRaw->getCpp();

  if (input.getRemainSize() < (inputPitch*h)) {
    if ((int)input.getRemainSize() > inputPitch)
      h = input.getRemainSize() / inputPitch - 1;
    else
      ThrowIOE("readUncompressedRaw: Not enough data to decode a single line. Image file truncated.");
  }
  if (bitPerPixel > 16)
    ThrowRDE("readUncompressedRaw: Unsupported bit depth");

  guint skipBits = inputPitch - w * bitPerPixel / 8;  // Skip per line
  if (offset.y > mRaw->dim.y)
    ThrowRDE("readUncompressedRaw: Invalid y offset");
  if (offset.x + size.x > mRaw->dim.x)
    ThrowRDE("readUncompressedRaw: Invalid x offset");

  guint y = offset.y;
  h = MIN(h + (guint)offset.y, (guint)mRaw->dim.y);

  if (MSBOrder) {
    BitPumpMSB bits(&input);
    w *= cpp;
    for (; y < h; y++) {
      gushort* dest = (gushort*) & data[offset.x*sizeof(gushort)*cpp+y*outPitch];
      bits.checkPos();
      for (guint x = 0 ; x < w; x++) {
        guint b = bits.getBits(bitPerPixel);
        dest[x] = b;
      }
      bits.skipBits(skipBits);
    }

  } else {

    if (bitPerPixel == 16)  {
      BitBlt(&data[offset.x*sizeof(gushort)*cpp+y*outPitch], outPitch,
             input.getData(), inputPitch, w*mRaw->bpp, h - y);
      return;
    }
    if (bitPerPixel == 12 && w == inputPitch * 8 / 12)  {
      Decode12BitRaw(input, w, h);
      return;
    }
    BitPumpPlain bits(&input);
    w *= cpp;
    for (; y < h; y++) {
      gushort* dest = (gushort*) & data[offset.x*sizeof(gushort)+y*outPitch];
      bits.checkPos();
      for (guint x = 0 ; x < w; x++) {
        guint b = bits.getBits(bitPerPixel);
        dest[x] = b;
      }
      bits.skipBits(skipBits);
    }
  }
}

void RawDecoder::Decode12BitRaw(ByteStream &input, guint w, guint h) {
  guchar* data = mRaw->getData();
  guint pitch = mRaw->pitch;
  const guchar *in = input.getData();
  if (input.getRemainSize() < ((w*12/8)*h)) {
    if ((int)input.getRemainSize() > (w*12/8))
      h = input.getRemainSize() / (w*12/8) - 1;
    else
      ThrowIOE("readUncompressedRaw: Not enough data to decode a single line. Image file truncated.");
  }
  for (guint y = 0; y < h; y++) {
    gushort* dest = (gushort*) & data[y*pitch];
    for (guint x = 0 ; x < w; x += 2) {
      guint g1 = *in++;
      guint g2 = *in++;
      dest[x] = g1 | ((g2 & 0xf) << 8);
      guint g3 = *in++;
      dest[x+1] = (g2 >> 4) | (g3 << 4);
    }
  }
}

void RawDecoder::checkCameraSupported(CameraMetaData *meta, string make, string model, string mode) {
  TrimSpaces(make);
  TrimSpaces(model);
  Camera* cam = meta->getCamera(make, model, mode);
  if (!cam) {
    if (mode.length() == 0)
      printf("Unable to find camera in database: %s %s %s\n", make.c_str(), model.c_str(), mode.c_str());

    return;    // Assume true.
  }

  if (!cam->supported)
    ThrowRDE("Camera not supported (explicit). Sorry.");

  if (cam->decoderVersion > decoderVersion)
    ThrowRDE("Camera not supported in this version. Update RawSpeed for support.");
}

void RawDecoder::setMetaData(CameraMetaData *meta, string make, string model, string mode) {
  TrimSpaces(make);
  TrimSpaces(model);
  Camera *cam = meta->getCamera(make, model, mode);
  if (!cam) {
    printf("Unable to find camera in database: %s %s %s\nPlease upload file to ftp.rawstudio.org, thanks!\n", make.c_str(), model.c_str(), mode.c_str());
    return;
  }

  iPoint2D new_size = cam->cropSize;

  // If crop size is negative, use relative cropping
  if (new_size.x <= 0)
    new_size.x = mRaw->dim.x - cam->cropPos.x + new_size.x;

  if (new_size.y <= 0)
    new_size.y = mRaw->dim.y - cam->cropPos.y + new_size.y;

  mRaw->subFrame(cam->cropPos, new_size);
  mRaw->cfa = cam->cfa;

  // Shift CFA to match crop
  if (cam->cropPos.x & 1)
    mRaw->cfa.shiftLeft();
  if (cam->cropPos.y & 1)
    mRaw->cfa.shiftDown();

  mRaw->blackLevel = cam->black;
  mRaw->whitePoint = cam->white;
}

void RawDecoder::TrimSpaces(string& str) {
  // Trim Both leading and trailing spaces
  size_t startpos = str.find_first_not_of(" \t"); // Find the first character position after excluding leading blank spaces
  size_t endpos = str.find_last_not_of(" \t"); // Find the first character position from reverse af

  // if all spaces or empty return an empty string
  if ((string::npos == startpos) || (string::npos == endpos)) {
    str = "";
  } else
    str = str.substr(startpos, endpos - startpos + 1);
}

void *RawDecoderDecodeThread(void *_this) {
  RawDecoderThread* me = (RawDecoderThread*)_this;
  try {
    me->parent->decodeThreaded(me);
  } catch (RawDecoderException ex) {
    me->error = _strdup(ex.what());
  } catch (IOException ex) {
    me->error = _strdup(ex.what());
  }

  pthread_exit(NULL);
  return 0;
}

void RawDecoder::startThreads() {
  guint threads;
#ifdef WIN32
  threads = pthread_num_processors_np();
#else
  // FIXME: Don't depend on Rawstudio.
  threads = rs_get_number_of_processor_cores();
#endif
  int y_offset = 0;
  int y_per_thread = (mRaw->dim.y + threads - 1) / threads;
  RawDecoderThread *t = new RawDecoderThread[threads];

  pthread_attr_t attr;

  /* Initialize and set thread detached attribute */
  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

  for (guint i = 0; i < threads; i++) {
    t[i].start_y = y_offset;
    t[i].end_y = MIN(y_offset + y_per_thread, mRaw->dim.y);
    t[i].parent = this;
    pthread_create(&t[i].threadid, &attr, RawDecoderDecodeThread, &t[i]);
    y_offset = t[i].end_y;
  }

  void *status;
  for (guint i = 0; i < threads; i++) {
    pthread_join(t[i].threadid, &status);
    if (t[i].error) {
      errors.push_back(t[i].error);
    }
  }
  delete[] t;
}

void RawDecoder::decodeThreaded(RawDecoderThread * t) {
  ThrowRDE("Internal Error: This class does not support threaded decoding");
}

} // namespace RawSpeed<|endoftext|>