<commit_before>/**
 * \file
 * \brief StaticRawMessageQueue and StaticRawMessageQueue2 classes header
 *
 * \author Copyright (C) 2015-2017 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef INCLUDE_DISTORTOS_STATICRAWMESSAGEQUEUE_HPP_
#define INCLUDE_DISTORTOS_STATICRAWMESSAGEQUEUE_HPP_

#include "distortos/RawMessageQueue.hpp"

#include "distortos/internal/memory/dummyDeleter.hpp"

namespace distortos
{

/**
 * \brief StaticRawMessageQueue2 class is a variant of RawMessageQueue that has automatic storage for queue's contents.
 *
 * This class is a replacement for StaticRawMessageQueue and StaticRawMessageQueueFromSize. To use this new API modify
 * your code in following way:
 * - `'StaticRawMessageQueue<T, QueueSize>'` -> `'StaticRawMessageQueue2<sizeof(T), QueueSize>'`;
 * - `'StaticRawMessageQueueFromSize<ElementSize, QueueSize>'` -> `'StaticRawMessageQueue2<ElementSize, QueueSize>'`;
 *
 * Transition schedule:
 * 1. v0.5.0 - `StaticRawMessageQueue<T, QueueSize>` and `StaticRawMessageQueueFromSize<ElementSize, QueueSize>` are
 * converted to deprecated aliases to `StaticRawMessageQueue2<ElementSize, QueueSize>`;
 * 2. v0.6.0 - "old" `StaticRawMessageQueue<T, QueueSize>` and `StaticRawMessageQueueFromSize<ElementSize, QueueSize>`
 * aliases are removed, `StaticRawMessageQueue2<ElementSize, QueueSize>` is renamed to
 * `StaticRawMessageQueue<ElementSize, QueueSize>`, deprecated `StaticRawMessageQueue2<ElementSize, QueueSize>` alias is
 * added;
 * 3. v0.7.0 - deprecated `StaticRawMessageQueue2<ElementSize, QueueSize>` alias is removed;
 *
 * \tparam ElementSize is the size of single queue element, bytes
 * \tparam QueueSize is the maximum number of elements in queue
 *
 * \ingroup queues
 */

template<size_t ElementSize, size_t QueueSize>
class StaticRawMessageQueue2 : public RawMessageQueue
{
public:

	/**
	 * \brief StaticRawMessageQueue2's constructor
	 */

	explicit StaticRawMessageQueue2() :
			RawMessageQueue{{entryStorage_.data(), internal::dummyDeleter<EntryStorage>},
					{valueStorage_.data(), internal::dummyDeleter<uint8_t>}, ElementSize, QueueSize}
	{

	}

private:

	/// storage for queue's entries
	std::array<EntryStorage, QueueSize> entryStorage_;

	/// storage for queue's contents
	std::array<uint8_t, ElementSize * QueueSize> valueStorage_;
};

/**
 * \brief StaticRawMessageQueue class is a variant of RawMessageQueue that has automatic storage for queue's contents.
 *
 * \deprecated scheduled to be removed after v0.5.0, use StaticRawMessageQueue2<sizeof(T), QueueSize>`
 *
 * \tparam T is the type of data in queue
 * \tparam QueueSize is the maximum number of elements in queue
 *
 * \ingroup queues
 */

template<typename T, size_t QueueSize>
using StaticRawMessageQueue __attribute__ ((deprecated("Use StaticRawMessageQueue2<sizeof(T), QueueSize>"))) =
		StaticRawMessageQueue2<sizeof(T), QueueSize>;

/**
 * \brief StaticRawMessageQueueFromSize type alias is a variant of StaticRawMessageQueue which uses size of element
 * (instead of type) as template argument.
 *
 * \tparam ElementSize is the size of single queue element, bytes
 * \tparam QueueSize is the maximum number of elements in queue
 */

template<size_t ElementSize, size_t QueueSize>
using StaticRawMessageQueueFromSize = StaticRawMessageQueue2<ElementSize, QueueSize>;

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_STATICRAWMESSAGEQUEUE_HPP_
<commit_msg>Mark StaticRawMessageQueueFromSize as deprecated<commit_after>/**
 * \file
 * \brief StaticRawMessageQueue and StaticRawMessageQueue2 classes header
 *
 * \author Copyright (C) 2015-2017 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#ifndef INCLUDE_DISTORTOS_STATICRAWMESSAGEQUEUE_HPP_
#define INCLUDE_DISTORTOS_STATICRAWMESSAGEQUEUE_HPP_

#include "distortos/RawMessageQueue.hpp"

#include "distortos/internal/memory/dummyDeleter.hpp"

namespace distortos
{

/**
 * \brief StaticRawMessageQueue2 class is a variant of RawMessageQueue that has automatic storage for queue's contents.
 *
 * This class is a replacement for StaticRawMessageQueue and StaticRawMessageQueueFromSize. To use this new API modify
 * your code in following way:
 * - `'StaticRawMessageQueue<T, QueueSize>'` -> `'StaticRawMessageQueue2<sizeof(T), QueueSize>'`;
 * - `'StaticRawMessageQueueFromSize<ElementSize, QueueSize>'` -> `'StaticRawMessageQueue2<ElementSize, QueueSize>'`;
 *
 * Transition schedule:
 * 1. v0.5.0 - `StaticRawMessageQueue<T, QueueSize>` and `StaticRawMessageQueueFromSize<ElementSize, QueueSize>` are
 * converted to deprecated aliases to `StaticRawMessageQueue2<ElementSize, QueueSize>`;
 * 2. v0.6.0 - "old" `StaticRawMessageQueue<T, QueueSize>` and `StaticRawMessageQueueFromSize<ElementSize, QueueSize>`
 * aliases are removed, `StaticRawMessageQueue2<ElementSize, QueueSize>` is renamed to
 * `StaticRawMessageQueue<ElementSize, QueueSize>`, deprecated `StaticRawMessageQueue2<ElementSize, QueueSize>` alias is
 * added;
 * 3. v0.7.0 - deprecated `StaticRawMessageQueue2<ElementSize, QueueSize>` alias is removed;
 *
 * \tparam ElementSize is the size of single queue element, bytes
 * \tparam QueueSize is the maximum number of elements in queue
 *
 * \ingroup queues
 */

template<size_t ElementSize, size_t QueueSize>
class StaticRawMessageQueue2 : public RawMessageQueue
{
public:

	/**
	 * \brief StaticRawMessageQueue2's constructor
	 */

	explicit StaticRawMessageQueue2() :
			RawMessageQueue{{entryStorage_.data(), internal::dummyDeleter<EntryStorage>},
					{valueStorage_.data(), internal::dummyDeleter<uint8_t>}, ElementSize, QueueSize}
	{

	}

private:

	/// storage for queue's entries
	std::array<EntryStorage, QueueSize> entryStorage_;

	/// storage for queue's contents
	std::array<uint8_t, ElementSize * QueueSize> valueStorage_;
};

/**
 * \brief StaticRawMessageQueue class is a variant of RawMessageQueue that has automatic storage for queue's contents.
 *
 * \deprecated scheduled to be removed after v0.5.0, use StaticRawMessageQueue2<sizeof(T), QueueSize>`
 *
 * \tparam T is the type of data in queue
 * \tparam QueueSize is the maximum number of elements in queue
 *
 * \ingroup queues
 */

template<typename T, size_t QueueSize>
using StaticRawMessageQueue __attribute__ ((deprecated("Use StaticRawMessageQueue2<sizeof(T), QueueSize>"))) =
		StaticRawMessageQueue2<sizeof(T), QueueSize>;

/**
 * \brief StaticRawMessageQueueFromSize type alias is a variant of StaticRawMessageQueue which uses size of element
 * (instead of type) as template argument.
 *
 * \deprecated scheduled to be removed after v0.5.0, use StaticRawMessageQueue2<ElementSize, QueueSize>`
 *
 * \tparam ElementSize is the size of single queue element, bytes
 * \tparam QueueSize is the maximum number of elements in queue
 */

template<size_t ElementSize, size_t QueueSize>
using StaticRawMessageQueueFromSize __attribute__ ((deprecated("Use StaticRawMessageQueue2<ElementSize, QueueSize>"))) =
		StaticRawMessageQueue2<ElementSize, QueueSize>;

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_STATICRAWMESSAGEQUEUE_HPP_
<|endoftext|>


<commit_before>#include "physics.h"
#include "GLDebugDrawer.h"
#include "../state/state.h"
#include <iostream>

using namespace Physics;

Simulation::Simulation()
{
	m_broadphase = new btDbvtBroadphase();
	m_collisionConfiguration = new btDefaultCollisionConfiguration();
	m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
	m_solver = new btSequentialImpulseConstraintSolver;
	m_world = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration);

	m_world->setGravity(btVector3(0,-10,0));

	mb.request(Events::EventType::Input);
}

Simulation::~Simulation()
{
	/*
	delete m_world;
	delete m_solver;
	delete m_broadphase;
	delete m_dispatcher;
	delete m_collisionConfiguration;
	*/
}

// Tuning
// Credit to:
// http://bullet.googlecode.com/svn-history/r2704/trunk/Demos/ForkLiftDemo/ForkLiftDemo.cpp
// Also:
// https://code.google.com/p/bullet/source/browse/trunk/Demos/VehicleDemo/VehicleDemo.cpp

float	gEngineForce = 0.0f;
float	gBrakingForce = 0.0f;

float	gVehicleSteering = 0.f;
float	wheelFriction = 1000;//BT_LARGE_FLOAT;
float	suspensionStiffness = 5.0f; //0.5f; //2.f;
float	suspensionDamping = 2.0f; //1.3f;
float	suspensionCompression = 0.3f; //1.1f;
float	suspensionTravelcm = 300.0f;
float	rollInfluence = 1.01f;//1.0f;
//btScalar suspensionRestLength(0.2);
btScalar suspensionRestLength(0.5);

btRigidBody *Simulation::addRigidBody(double mass, const btTransform& startTransform, btCollisionShape* shape)
{
	btVector3 localInertia(0, 0, 0);
	if (mass != 0.0) {
		shape->calculateLocalInertia((btScalar)mass, localInertia);
	}

	btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);

	btRigidBody::btRigidBodyConstructionInfo cInfo((btScalar)mass,myMotionState,shape,localInertia);

	btRigidBody* body = new btRigidBody(cInfo);
	body->setContactProcessingThreshold(1);

	m_world->addRigidBody(body);

	return body;
}

int Simulation::loadWorld()
{
	// Create car
#define CAR_WIDTH (0.15f)
#define CAR_LENGTH (0.25f)
#define CAR_MASS (200.0f)

	btCollisionShape* chassisShape = new btBoxShape(btVector3(CAR_WIDTH, CAR_WIDTH, CAR_LENGTH));
	btCompoundShape* compound = new btCompoundShape();
	m_collisionShapes.push_back(chassisShape);
	m_collisionShapes.push_back(compound);

	btTransform localTrans; // shift gravity to center of car
	localTrans.setIdentity();
	localTrans.setOrigin(btVector3(0,CAR_WIDTH*1, 0));
	compound->addChildShape(localTrans, chassisShape);

	btTransform tr;
	tr.setIdentity();
	tr.setOrigin(btVector3(0,5,0));		// This sets where the car initially spawns
	m_carChassis = addRigidBody(CAR_MASS, tr, compound);

	m_vehicleRayCaster = new btDefaultVehicleRaycaster(m_world);

	m_vehicle = new btRaycastVehicle(m_tuning,m_carChassis, m_vehicleRayCaster);
	m_carChassis->setActivationState(DISABLE_DEACTIVATION);
	m_vehicle->setCoordinateSystem(0,1,0);
	m_world->addVehicle(m_vehicle);

	float connectionHeight = 0.15f;
	btVector3 wheelDirectionCS0(0,-1,0);
	btVector3 wheelAxleCS(-1,0,0);

#define CON1 (CAR_WIDTH)
#define CON2 (CAR_LENGTH)

	float	wheelRadius = 0.075f;
	float	wheelWidth = 0.02f;

	// Setup front 2 wheels
	bool isFrontWheel=true;
	btVector3 connectionPointCS0(CON1,connectionHeight,CON2);
	m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_tuning,isFrontWheel);

	connectionPointCS0 = btVector3(-CON1,connectionHeight,CON2);
	m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_tuning,isFrontWheel);

	// Setup rear  2 wheels
	isFrontWheel = false;

	connectionPointCS0 = btVector3(-CON1,connectionHeight,-CON2);
	m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_tuning,isFrontWheel);

	connectionPointCS0 = btVector3(CON1,connectionHeight,-CON2);
	m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_tuning,isFrontWheel);

	for (int i=0;i<m_vehicle->getNumWheels();i++)
	{
		btWheelInfo& wheel = m_vehicle->getWheelInfo(i);

		wheel.m_maxSuspensionTravelCm = suspensionTravelcm;
		wheel.m_suspensionStiffness = suspensionStiffness;
		wheel.m_wheelsDampingRelaxation = suspensionDamping;
		wheel.m_wheelsDampingCompression = suspensionCompression;
		wheel.m_frictionSlip = wheelFriction;
		wheel.m_rollInfluence = rollInfluence;
	}

	// Add map
	StateData *state = GetMutState();
	btBvhTriangleMeshShape *arenaShape = new btBvhTriangleMeshShape(state->bttmArena, true, true);
	m_arena = addRigidBody(0.0, btTransform(btQuaternion(0,0,0,1),btVector3(0,0,0)), arenaShape);

	for (int i=0;i<m_vehicle->getNumWheels();i++)
	{
		//synchronize the wheels with the (interpolated) chassis worldtransform
		m_vehicle->updateWheelTransform(i,true);
	}

	return 0;
}

void Simulation::step(double seconds)
{
	// DEBUGOUT("RUNING PHYSICS %lf\n", seconds);

#define STEER_MAX_ANGLE (40)
#define ENGINE_MAX_FORCE (1000)
<<<<<<< HEAD
#define BRAKE_MAX_FORCE (800)
#define E_BRAKE_FORCE (300)
#define MAX_SPEED (10)
=======
#define BRAKE_MAX_FORCE (3000)
>>>>>>> 639e5dce51abaedf2ae0496c4bc9a348e2656f30

	for ( Events::Event *event : (mb.checkMail()) )
	{
		// Hack: Sorry
		switch ( event->type )
		{
<<<<<<< HEAD
		case Events::EventType::Input:
		{
			Events::InputEvent *input = (Events::InputEvent *)event;

			if(input->bPressed)	// E Brake turn
			{
				gEngineForce = 0;
				gBrakingForce = E_BRAKE_FORCE;

				// Could maybe apply a sideways force to the back of the car based on turning direction
				// Set wheel friction super low

			}
			else
			{
				gBrakingForce = 0.0;
				gVehicleSteering = -STEER_MAX_ANGLE * input->leftThumbStickRL;
				if(m_vehicle->getCurrentSpeedKmHour() < MAX_SPEED)
					gEngineForce = ENGINE_MAX_FORCE * input->rightTrigger - BRAKE_MAX_FORCE * input->leftTrigger;
				else
					gEngineForce = 0;
			}

			DEBUGOUT("Bforce: %lf, Eforce: %lf, Steer: %f\n", gBrakingForce, gEngineForce, gVehicleSteering);
			//DEBUGOUT("Speed: %f\n", (float)m_vehicle->getCurrentSpeedKmHour());
		}
=======
			case Events::EventType::Input:
			{
				Events::InputEvent *input = (Events::InputEvent *)event;

				//double steer = STEER_MAX_ANGLE * input->leftThumbStickRL;
				//if (steer) {
				//	gVehicleSteering = steer;
				//}
				////DEBUGOUT("STEER %lf, ", gVehicleSteering);
				//double force = ENGINE_MAX_FORCE * input->rightTrigger;
				//if(force) {
				//	gEngineForce = force;
				//}
				////DEBUGOUT("FORCE %lf\n", gEngineForce);
				//double breakingForce = BRAKE_MAX_FORCE * input->leftTrigger;
				//if(breakingForce)
				//{
				//	//gBreakingForce = breakingForce;
				//	gBreakingForce = 0.0;
				//	gEngineForce -= breakingForce;
				//}

				gBrakingForce = 0.0;	// Not using this yet, maybe for E-brake or something.
				gVehicleSteering = DEGTORAD(STEER_MAX_ANGLE) * input->leftThumbStickRL;
				gEngineForce = ENGINE_MAX_FORCE * input->rightTrigger - BRAKE_MAX_FORCE * input->leftTrigger;

				DEBUGOUT("Bforce: %lf, Eforce: %lf, Steer: %f\n", gBrakingForce, gEngineForce, gVehicleSteering);

				if( GetState().key_map['r'] )
				{
					btTransform trans;
					trans.setOrigin( btVector3( 0, 5, 0 ) );
					m_vehicle->getRigidBody()->setWorldTransform( trans );
				}
			}
>>>>>>> 639e5dce51abaedf2ae0496c4bc9a348e2656f30
			break;

		default:
			break;
		}
	}
	mb.emptyMail();

	// Apply steering to front wheels
	m_vehicle->setSteeringValue(gVehicleSteering, 0);
	m_vehicle->setSteeringValue(gVehicleSteering, 1);

	// Apply braking and engine force to rear wheels
	m_vehicle->applyEngineForce(gEngineForce, 2);
	m_vehicle->applyEngineForce(gEngineForce, 3);
	m_vehicle->setBrake(gBrakingForce, 2);
	m_vehicle->setBrake(gBrakingForce, 3);

	m_world->stepSimulation((btScalar)seconds, 10);

	UpdateGameState();
}

// Updates the car placement in the world state
void Simulation::UpdateGameState()
{
	StateData *state = GetMutState();
	btTransform car1 = m_vehicle->getChassisWorldTransform();

	btVector3 pos = car1.getOrigin();
	state->Karts[0].vPos.x = (Real)pos.getX();
	state->Karts[0].vPos.y = (Real)pos.getY();
	state->Karts[0].vPos.z = (Real)pos.getZ();

	btQuaternion rot = car1.getRotation();
	state->Karts[0].qOrient.x = (Real)rot.getX();
	state->Karts[0].qOrient.y = (Real)-rot.getY();
	state->Karts[0].qOrient.z = (Real)rot.getZ();
	state->Karts[0].qOrient.w = (Real)rot.getW();
}

void Simulation::enableDebugView()
{
}
<commit_msg>Fixed car reset to clear the vehicle's velocity.<commit_after>#include "physics.h"
#include "GLDebugDrawer.h"
#include "../state/state.h"
#include <iostream>

using namespace Physics;

Simulation::Simulation()
{
	m_broadphase = new btDbvtBroadphase();
	m_collisionConfiguration = new btDefaultCollisionConfiguration();
	m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);
	m_solver = new btSequentialImpulseConstraintSolver;
	m_world = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration);

	m_world->setGravity(btVector3(0,-10,0));

	mb.request(Events::EventType::Input);
}

Simulation::~Simulation()
{
	/*
	delete m_world;
	delete m_solver;
	delete m_broadphase;
	delete m_dispatcher;
	delete m_collisionConfiguration;
	*/
}

// Tuning
// Credit to:
// http://bullet.googlecode.com/svn-history/r2704/trunk/Demos/ForkLiftDemo/ForkLiftDemo.cpp
// Also:
// https://code.google.com/p/bullet/source/browse/trunk/Demos/VehicleDemo/VehicleDemo.cpp

float	gEngineForce = 0.0f;
float	gBrakingForce = 0.0f;

float	gVehicleSteering = 0.f;
float	wheelFriction = 1000;//BT_LARGE_FLOAT;
float	suspensionStiffness = 5.0f; //0.5f; //2.f;
float	suspensionDamping = 2.0f; //1.3f;
float	suspensionCompression = 0.3f; //1.1f;
float	suspensionTravelcm = 300.0f;
float	rollInfluence = 1.01f;//1.0f;
//btScalar suspensionRestLength(0.2);
btScalar suspensionRestLength(0.5);

btRigidBody *Simulation::addRigidBody(double mass, const btTransform& startTransform, btCollisionShape* shape)
{
	btVector3 localInertia(0, 0, 0);
	if (mass != 0.0) {
		shape->calculateLocalInertia((btScalar)mass, localInertia);
	}

	btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform);

	btRigidBody::btRigidBodyConstructionInfo cInfo((btScalar)mass,myMotionState,shape,localInertia);

	btRigidBody* body = new btRigidBody(cInfo);
	body->setContactProcessingThreshold(1);

	m_world->addRigidBody(body);

	return body;
}

int Simulation::loadWorld()
{
	// Create car
#define CAR_WIDTH (0.15f)
#define CAR_LENGTH (0.25f)
#define CAR_MASS (200.0f)

	btCollisionShape* chassisShape = new btBoxShape(btVector3(CAR_WIDTH, CAR_WIDTH, CAR_LENGTH));
	btCompoundShape* compound = new btCompoundShape();
	m_collisionShapes.push_back(chassisShape);
	m_collisionShapes.push_back(compound);

	btTransform localTrans; // shift gravity to center of car
	localTrans.setIdentity();
	localTrans.setOrigin(btVector3(0,CAR_WIDTH*1, 0));
	compound->addChildShape(localTrans, chassisShape);

	btTransform tr;
	tr.setIdentity();
	tr.setOrigin(btVector3(0,5,0));		// This sets where the car initially spawns
	m_carChassis = addRigidBody(CAR_MASS, tr, compound);

	m_vehicleRayCaster = new btDefaultVehicleRaycaster(m_world);

	m_vehicle = new btRaycastVehicle(m_tuning,m_carChassis, m_vehicleRayCaster);
	m_carChassis->setActivationState(DISABLE_DEACTIVATION);
	m_vehicle->setCoordinateSystem(0,1,0);
	m_world->addVehicle(m_vehicle);

	float connectionHeight = 0.15f;
	btVector3 wheelDirectionCS0(0,-1,0);
	btVector3 wheelAxleCS(-1,0,0);

#define CON1 (CAR_WIDTH)
#define CON2 (CAR_LENGTH)

	float	wheelRadius = 0.075f;
	float	wheelWidth = 0.02f;

	// Setup front 2 wheels
	bool isFrontWheel=true;
	btVector3 connectionPointCS0(CON1,connectionHeight,CON2);
	m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_tuning,isFrontWheel);

	connectionPointCS0 = btVector3(-CON1,connectionHeight,CON2);
	m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_tuning,isFrontWheel);

	// Setup rear  2 wheels
	isFrontWheel = false;

	connectionPointCS0 = btVector3(-CON1,connectionHeight,-CON2);
	m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_tuning,isFrontWheel);

	connectionPointCS0 = btVector3(CON1,connectionHeight,-CON2);
	m_vehicle->addWheel(connectionPointCS0,wheelDirectionCS0,wheelAxleCS,suspensionRestLength,wheelRadius,m_tuning,isFrontWheel);

	for (int i=0;i<m_vehicle->getNumWheels();i++)
	{
		btWheelInfo& wheel = m_vehicle->getWheelInfo(i);

		wheel.m_maxSuspensionTravelCm = suspensionTravelcm;
		wheel.m_suspensionStiffness = suspensionStiffness;
		wheel.m_wheelsDampingRelaxation = suspensionDamping;
		wheel.m_wheelsDampingCompression = suspensionCompression;
		wheel.m_frictionSlip = wheelFriction;
		wheel.m_rollInfluence = rollInfluence;
	}

	// Add map
	StateData *state = GetMutState();
	btBvhTriangleMeshShape *arenaShape = new btBvhTriangleMeshShape(state->bttmArena, true, true);
	m_arena = addRigidBody(0.0, btTransform(btQuaternion(0,0,0,1),btVector3(0,0,0)), arenaShape);

	for (int i=0;i<m_vehicle->getNumWheels();i++)
	{
		//synchronize the wheels with the (interpolated) chassis worldtransform
		m_vehicle->updateWheelTransform(i,true);
	}

	return 0;
}

void Simulation::step(double seconds)
{
	// DEBUGOUT("RUNING PHYSICS %lf\n", seconds);

#define STEER_MAX_ANGLE (40)
#define ENGINE_MAX_FORCE (1000)
#define BRAKE_MAX_FORCE (800)
#define E_BRAKE_FORCE (100)
#define MAX_SPEED (10)

	for ( Events::Event *event : (mb.checkMail()) )
	{
		// Hack: Sorry
		switch ( event->type )
		{
		case Events::EventType::Input:
		{
			Events::InputEvent *input = (Events::InputEvent *)event;

			if(input->bPressed)	// E Brake turn
			{
				//gEngineForce = 0;
				gBrakingForce = E_BRAKE_FORCE;

				// Could maybe apply a sideways force to the back of the car based on turning direction
				// Set wheel friction super low
			}
			else
			{
				gBrakingForce = 0.0;
				gVehicleSteering = DEGTORAD(STEER_MAX_ANGLE) * input->leftThumbStickRL;

				if(m_vehicle->getCurrentSpeedKmHour() < MAX_SPEED)
					gEngineForce = ENGINE_MAX_FORCE * input->rightTrigger - BRAKE_MAX_FORCE * input->leftTrigger;
				else
					gEngineForce = 0;
			}

			if( GetState().key_map['r'] )
			{
				btTransform trans;
				trans.setOrigin( btVector3( 0, 5, 0 ) );
				m_vehicle->getRigidBody()->setLinearVelocity(btVector3(0,0,0));
				m_vehicle->getRigidBody()->setWorldTransform( trans );
			}

			DEBUGOUT("Bforce: %lf, Eforce: %lf, Steer: %f\n", gBrakingForce, gEngineForce, gVehicleSteering);
			//DEBUGOUT("Speed: %f\n", (float)m_vehicle->getCurrentSpeedKmHour());
		}
		default:
			break;
		}
	}
	mb.emptyMail();

	// Apply steering to front wheels
	m_vehicle->setSteeringValue(gVehicleSteering, 0);
	m_vehicle->setSteeringValue(gVehicleSteering, 1);

	// Apply braking and engine force to rear wheels
	m_vehicle->applyEngineForce(gEngineForce, 2);
	m_vehicle->applyEngineForce(gEngineForce, 3);
	m_vehicle->setBrake(gBrakingForce, 2);
	m_vehicle->setBrake(gBrakingForce, 3);

	m_world->stepSimulation((btScalar)seconds, 10);

	UpdateGameState();
}

// Updates the car placement in the world state
void Simulation::UpdateGameState()
{
	StateData *state = GetMutState();
	btTransform car1 = m_vehicle->getChassisWorldTransform();

	btVector3 pos = car1.getOrigin();
	state->Karts[0].vPos.x = (Real)pos.getX();
	state->Karts[0].vPos.y = (Real)pos.getY();
	state->Karts[0].vPos.z = (Real)pos.getZ();

	btQuaternion rot = car1.getRotation();
	state->Karts[0].qOrient.x = (Real)rot.getX();
	state->Karts[0].qOrient.y = (Real)-rot.getY();
	state->Karts[0].qOrient.z = (Real)rot.getZ();
	state->Karts[0].qOrient.w = (Real)rot.getW();
}

void Simulation::enableDebugView()
{
}
<|endoftext|>


<commit_before><commit_msg>Planning: add detailed information<commit_after><|endoftext|>


<commit_before>// Filename: internalName_ext.I
// Created by:  rdb (28Sep14)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University.  All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license.  You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////

#include "internalName_ext.h"

#ifdef HAVE_PYTHON

////////////////////////////////////////////////////////////////////
//     Function: InternalName::make
//       Access: Published, Static
//  Description: This extension method serves to allow coercion of
//               Python interned strings to InternalName objects
//               more efficiently by storing a mapping between
//               Python and Panda interned strings.
////////////////////////////////////////////////////////////////////
#if PY_MAJOR_VERSION >= 3
PT(InternalName) Extension<InternalName>::
make(PyUnicodeObject *str) {
  if (!PyUnicode_CHECK_INTERNED(str)) {
    // Not an interned string; don't bother.
    Py_ssize_t len = 0;
    char *c_str = PyUnicode_AsUTF8AndSize((PyObject *)str, &len);
    if (c_str == NULL) {
      return NULL;
    }

    string name(c_str, len);
    return InternalName::make(c_str, len);
  }

  InternalName::PyInternTable::const_iterator it;
  it = InternalName::_py_intern_table.find((PyObject*)str);

  if (it != InternalName::_py_intern_table.end()) {
    return (*it).second;

  } else {
    Py_ssize_t len = 0;
    char *c_str = PyUnicode_AsUTF8AndSize((PyObject *)str, &len);
    string name(c_str, len);

#else
PT(InternalName) Extension<InternalName>::
make(PyStringObject *str) {
  if (!PyString_CHECK_INTERNED(str)) {
    // Not an interned string; don't bother.
    string name(PyString_AS_STRING(str), PyString_GET_SIZE(str));
    return InternalName::make(name);
  }

  InternalName::PyInternTable::const_iterator it;
  it = InternalName::_py_intern_table.find((PyObject*)str);

  if (it != InternalName::_py_intern_table.end()) {
    return (*it).second;

  } else {
    string name(PyString_AS_STRING(str), PyString_GET_SIZE(str));

#endif  // PY_MAJOR_VERSION

    PT(InternalName) iname = InternalName::make(name);

    // We basically leak references to both the PyObject and the
    // InternalName.  We may want to change that in the future if it
    // becomes a problem.
    Py_INCREF(str);
    iname->ref();

    InternalName::_py_intern_table.insert(make_pair((PyObject *)str, iname.p()));
    return iname.p();
  }

}

#endif  // HAVE_PYTHON
<commit_msg>Fix coercion of non-interned strings in Python 3<commit_after>// Filename: internalName_ext.I
// Created by:  rdb (28Sep14)
//
////////////////////////////////////////////////////////////////////
//
// PANDA 3D SOFTWARE
// Copyright (c) Carnegie Mellon University.  All rights reserved.
//
// All use of this software is subject to the terms of the revised BSD
// license.  You should have received a copy of this license along
// with this source code in a file named "LICENSE."
//
////////////////////////////////////////////////////////////////////

#include "internalName_ext.h"

#ifdef HAVE_PYTHON

////////////////////////////////////////////////////////////////////
//     Function: InternalName::make
//       Access: Published, Static
//  Description: This extension method serves to allow coercion of
//               Python interned strings to InternalName objects
//               more efficiently by storing a mapping between
//               Python and Panda interned strings.
////////////////////////////////////////////////////////////////////
#if PY_MAJOR_VERSION >= 3
PT(InternalName) Extension<InternalName>::
make(PyUnicodeObject *str) {
  if (!PyUnicode_CHECK_INTERNED(str)) {
    // Not an interned string; don't bother.
    Py_ssize_t len = 0;
    char *c_str = PyUnicode_AsUTF8AndSize((PyObject *)str, &len);
    if (c_str == NULL) {
      return NULL;
    }

    string name(c_str, len);
    return InternalName::make(name);
  }

  InternalName::PyInternTable::const_iterator it;
  it = InternalName::_py_intern_table.find((PyObject*)str);

  if (it != InternalName::_py_intern_table.end()) {
    return (*it).second;

  } else {
    Py_ssize_t len = 0;
    char *c_str = PyUnicode_AsUTF8AndSize((PyObject *)str, &len);
    string name(c_str, len);

#else
PT(InternalName) Extension<InternalName>::
make(PyStringObject *str) {
  if (!PyString_CHECK_INTERNED(str)) {
    // Not an interned string; don't bother.
    string name(PyString_AS_STRING(str), PyString_GET_SIZE(str));
    return InternalName::make(name);
  }

  InternalName::PyInternTable::const_iterator it;
  it = InternalName::_py_intern_table.find((PyObject*)str);

  if (it != InternalName::_py_intern_table.end()) {
    return (*it).second;

  } else {
    string name(PyString_AS_STRING(str), PyString_GET_SIZE(str));

#endif  // PY_MAJOR_VERSION

    PT(InternalName) iname = InternalName::make(name);

    // We basically leak references to both the PyObject and the
    // InternalName.  We may want to change that in the future if it
    // becomes a problem.
    Py_INCREF(str);
    iname->ref();

    InternalName::_py_intern_table.insert(make_pair((PyObject *)str, iname.p()));
    return iname.p();
  }

}

#endif  // HAVE_PYTHON
<|endoftext|>


<commit_before>/*
 * Copyright 2007-2021 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "regex.hxx"
#include "expand.hxx"
#include "pcre/Regex.hxx"

#include <assert.h>
#include <string.h>

size_t
ExpandStringLength(const char *src, const MatchInfo &match_info)
{
    struct Result {
        size_t result = 0;

        void Append(gcc_unused char ch) {
            ++result;
        }

        void Append(const char *p) {
            result += strlen(p);
        }

        void Append(gcc_unused const char *p, size_t length) {
            result += length;
        }

        void AppendValue(gcc_unused const char *p, size_t length) {
            result += length;
        }

        size_t Commit() const {
            return result;
        }
    };

    Result result;
    ExpandString(result, src, match_info);
    return result.Commit();
}
<commit_msg>regex: remove "gcc_unused" attribute<commit_after>/*
 * Copyright 2007-2021 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "regex.hxx"
#include "expand.hxx"
#include "pcre/Regex.hxx"

#include <assert.h>
#include <string.h>

size_t
ExpandStringLength(const char *src, const MatchInfo &match_info)
{
    struct Result {
        size_t result = 0;

        void Append(char) {
            ++result;
        }

        void Append(const char *p) {
            result += strlen(p);
        }

        void Append(const char *, size_t length) {
            result += length;
        }

        void AppendValue(const char *, size_t length) {
            result += length;
        }

        size_t Commit() const {
            return result;
        }
    };

    Result result;
    ExpandString(result, src, match_info);
    return result.Commit();
}
<|endoftext|>


<commit_before>#include <boost/smart_ptr.hpp>
#include <iostream>

using namespace std;
using namespace boost;
class node_son
{
public:
	node_son(int v):x(v){};
        ~node_son()
        {       cout << "son deleted" << x << endl;}
        int x;
};
class node
{
public:
	node(int v):x(v), son(v * 10)
	{}
	~node()
	{	cout << "deleted" << x << endl;}
	int x;

	typedef shared_ptr<node> ptr_type;
	ptr_type next;
	node_son son;
};
//智能指针循环引用为什么导致　智能指针失效呢，搞不懂
//
int main()
{

	shared_ptr<node> p1(new node(1)); //make_shared<node>();
	shared_ptr<node> p2(new node(2)); //make_shared<node>();
	cout << "p1 use:" << p1.use_count() << endl;
	cout << "p2 use:" << p2.use_count() << endl;

	p1->next = p2;
	p2->next = p1;
        cout << "p1 use:" << p1.use_count() << endl;
        cout << "p2 use:" << p2.use_count() << endl;
	//p1->next.reset();
	//p1.reset();
        cout << "p1 use:" << p1.use_count() << endl;
        cout << "p2 use:" << p2.use_count() << endl;
	//p2->next.reset();
	//p2.reset();
	cout << "p1 use:" << p1.use_count() << endl;
        cout << "p2 use:" << p2.use_count() << endl;
	node s(3);

}

<commit_msg>循环指针计数器探析<commit_after>#include <boost/smart_ptr.hpp>
#include <iostream>

using namespace std;
using namespace boost;
class node_son
{
public:
	node_son(int v):x(v){};
        ~node_son()
        {       cout << "son deleted" << x << endl;}
        int x;
};
class node
{
public:
	node(int v):x(v), son(v * 10)
	{}
	~node()
	{	cout << "deleted" << x << endl;}
	int x;

	typedef shared_ptr<node> ptr_type;
	ptr_type next;
	node_son son;
};
/* 智能指针循环引用为什么导致　智能指针失效呢，搞不懂

回答：因为内部p1->next需要引用计数为0的时候才会删除 p1 与 p1-next
退出的时候析构顺序如下:
首先p1计数器 -1，因为p2-next = p1的原因 p1.use_count() = 1 p1 不会析构，因此p1->next依然有效
然后p2计数器 -1 因为p1->next = p2依然有效 p2也不会自动析构
这样就存在内存泄露的情况了。
我之前的错误分析想法也记录一下:
 首先 p1 计数器 -1， 然后 p1->next释放 p2 计数器 -1，
 然后 p2 计数器 -1， 然后 p2->next释放 p1 计数器 -1，

*/
int main()
{

	shared_ptr<node> p1(new node(1)); //make_shared<node>();
	shared_ptr<node> p2(new node(2)); //make_shared<node>();
	cout << "p1 use:" << p1.use_count() << endl;
	cout << "p2 use:" << p2.use_count() << endl;

	p1->next = p2;
	p2->next = p1;
        cout << "p1 use:" << p1.use_count() << endl;
        cout << "p2 use:" << p2.use_count() << endl;
	//p1->next.reset();
	//p1.reset();
        cout << "p1 use:" << p1.use_count() << endl;
        cout << "p2 use:" << p2.use_count() << endl;
	//p2->next.reset();
	//p2.reset();
	cout << "p1 use:" << p1.use_count() << endl;
        cout << "p2 use:" << p2.use_count() << endl;
	node s(3);

}

<|endoftext|>


<commit_before>#pragma once

#include <memory_resource>

#include "nova_renderer/memory/bytes.hpp"
#include "nova_renderer/memory/host_memory_resource.hpp"

namespace nova::mem {
    template <typename AllocatedType = std::byte>
    class AllocatorHandle : public std::pmr::polymorphic_allocator<AllocatedType> {
    public:
        AllocatorHandle() = default;

        explicit AllocatorHandle(std::pmr::memory_resource* memory);

        AllocatorHandle(const AllocatorHandle& other) = delete;
        AllocatorHandle& operator=(const AllocatorHandle& other) = delete;

        AllocatorHandle(AllocatorHandle&& old) noexcept = default;
        AllocatorHandle& operator=(AllocatorHandle&& old) noexcept = default;

        virtual ~AllocatorHandle() = default;

        /*!
         * \brief Allocates and constructs an object of the specified type
         *
         * Would be nice if C++ came with this method, but nope not yet
         */
        template <typename... Args>
        AllocatedType* new_object(Args&&... args);

        /*!
         * \brief Allocates an object of a different type than what this allocator normally created
         *
         * Intended use case is that you have a byte allocator that you allocate a few different object types from
         */
        template <typename ObjectType, typename = std::enable_if_t<std::is_same_v<AllocatedType, std::byte>>>
        ObjectType* allocate_object();

        /*!
         * \brief Allocates a shared pointer that uses this allocator to allocate its internal memory
         *
         * \param deleter A functor that you want to use to delete the object
         * \param args Any arguments to forward to the new object's constructor
         *
         * \return A shared pointer to the new object
         */
        template <typename ObjectType,
                  typename DeleterType,
                  typename... Args,
                  typename = std::enable_if_t<std::is_same_v<AllocatedType, std::byte>>>
        std::shared_ptr<ObjectType> allocate_shared(DeleterType deleter, Args&&... args);

        /*!
         * \brief Allocates and constructs an object of a different type
         *
         * Intended use case is that you have a byte allocator that you use to create objects of different types
         */
        template <typename ObjectType, typename... Args, typename = std::enable_if_t<std::is_same_v<AllocatedType, std::byte>>>
        ObjectType* new_other_object(Args&&... args);

        /*!
         * \brief Creates a new allocator which will allocate from this allocator's memory resource
         */
        template <typename ObjectType = AllocatedType, typename = std::enable_if_t<std::is_same_v<AllocatedType, std::byte>>>
        AllocatorHandle<ObjectType>* create_suballocator();
    };

    template <typename AllocatedType = std::byte>
    AllocatorHandle<AllocatedType> get_malloc_allocator() {
        return AllocatorHandle<AllocatedType>(std::pmr::new_delete_resource());
    }

    template <typename AllocatedType>
    AllocatorHandle<AllocatedType>::AllocatorHandle(std::pmr::memory_resource* memory)
        : std::pmr::polymorphic_allocator<AllocatedType>(memory) {}

    template <typename AllocatedType>
    template <typename... Args>
    AllocatedType* AllocatorHandle<AllocatedType>::new_object(Args&&... args) {
        auto* mem = this->allocate(1);
        this->construct(mem, args...);
        return mem;
    }

    template <typename AllocatedType>
    template <typename ObjectType, typename>
    ObjectType* AllocatorHandle<AllocatedType>::allocate_object() {
        auto* mem = this->allocate(sizeof(ObjectType));
        return reinterpret_cast<ObjectType*>(mem);
    }

    template <typename AllocatedType>
    template <typename ObjectType, typename DeleterType, typename... Args, typename>
    std::shared_ptr<ObjectType> AllocatorHandle<AllocatedType>::allocate_shared(DeleterType deleter, Args&&... args) {
        const auto ptr = allocate_object<ObjectType>(std::forward(args)...);
        return std::shared_ptr<ObjectType>(ptr, deleter, std::pmr::polymorphic_allocator<std::byte>(this->resource()));
    }

    template <typename AllocatedType>
    template <typename ObjectType, typename... Args, typename>
    ObjectType* AllocatorHandle<AllocatedType>::new_other_object(Args&&... args) {
        auto* mem = this->allocate(sizeof(ObjectType));
        return new(mem) ObjectType(std::forward<Args>(args)...);
    }

    template <typename AllocatedType>
    template <typename ObjectType, typename>
    AllocatorHandle<ObjectType>* AllocatorHandle<AllocatedType>::create_suballocator() {
        return this->template new_other_object<AllocatorHandle<ObjectType>>(this->resource());
    }
} // namespace nova::mem
<commit_msg>[memory] SFINAE shows us just how shitty the C++ standards committee is<commit_after>#pragma once

#include <memory_resource>

#include "nova_renderer/memory/bytes.hpp"
#include "nova_renderer/memory/host_memory_resource.hpp"

namespace nova::mem {
    template <typename AllocatedType = std::byte>
    class AllocatorHandle : public std::pmr::polymorphic_allocator<AllocatedType> {
    public:
        AllocatorHandle() = default;

        explicit AllocatorHandle(std::pmr::memory_resource* memory);

        AllocatorHandle(const AllocatorHandle& other) = delete;
        AllocatorHandle& operator=(const AllocatorHandle& other) = delete;

        AllocatorHandle(AllocatorHandle&& old) noexcept = default;
        AllocatorHandle& operator=(AllocatorHandle&& old) noexcept = default;

        virtual ~AllocatorHandle() = default;

        /*!
         * \brief Allocates and constructs an object of the specified type
         *
         * Would be nice if C++ came with this method, but nope not yet
         */
        template <typename... Args>
        AllocatedType* new_object(Args&&... args);

        /*!
         * \brief Allocates an object of a different type than what this allocator normally created
         *
         * Intended use case is that you have a byte allocator that you allocate a few different object types from
         */
        template <typename ObjectType>
        ObjectType* allocate_object();

        /*!
         * \brief Allocates a shared pointer that uses this allocator to allocate its internal memory
         *
         * \param deleter A functor that you want to use to delete the object
         * \param args Any arguments to forward to the new object's constructor
         *
         * \return A shared pointer to the new object
         */
        template <typename ObjectType,
                  typename DeleterType,
                  typename... Args>
        std::shared_ptr<ObjectType> allocate_shared(DeleterType deleter, Args&&... args);

        /*!
         * \brief Allocates and constructs an object of a different type
         *
         * Intended use case is that you have a byte allocator that you use to create objects of different types
         */
        template <typename ObjectType, typename... Args>
        ObjectType* new_other_object(Args&&... args);

        /*!
         * \brief Creates a new allocator which will allocate from this allocator's memory resource
         */
        template <typename ObjectType = AllocatedType>
        AllocatorHandle<ObjectType>* create_suballocator();
    };

    template <typename AllocatedType = std::byte>
    AllocatorHandle<AllocatedType> get_malloc_allocator() {
        return AllocatorHandle<AllocatedType>(std::pmr::new_delete_resource());
    }

    template <typename AllocatedType>
    AllocatorHandle<AllocatedType>::AllocatorHandle(std::pmr::memory_resource* memory)
        : std::pmr::polymorphic_allocator<AllocatedType>(memory) {}

    template <typename AllocatedType>
    template <typename... Args>
    AllocatedType* AllocatorHandle<AllocatedType>::new_object(Args&&... args) {
        auto* mem = this->allocate(1);
        this->construct(mem, args...);
        return mem;
    }

    template <typename AllocatedType>
    template <typename ObjectType>
    ObjectType* AllocatorHandle<AllocatedType>::allocate_object() {
        auto* mem = this->allocate(sizeof(ObjectType));
        return reinterpret_cast<ObjectType*>(mem);
    }

    template <typename AllocatedType>
    template <typename ObjectType, typename DeleterType, typename... Args>
    std::shared_ptr<ObjectType> AllocatorHandle<AllocatedType>::allocate_shared(DeleterType deleter, Args&&... args) {
        const auto ptr = allocate_object<ObjectType>(std::forward(args)...);
        return std::shared_ptr<ObjectType>(ptr, deleter, std::pmr::polymorphic_allocator<std::byte>(this->resource()));
    }

    template <typename AllocatedType>
    template <typename ObjectType, typename... Args>
    ObjectType* AllocatorHandle<AllocatedType>::new_other_object(Args&&... args) {
        auto* mem = this->allocate(sizeof(ObjectType));
        return new(mem) ObjectType(std::forward<Args>(args)...);
    }

    template <typename AllocatedType>
    template <typename ObjectType>
    AllocatorHandle<ObjectType>* AllocatorHandle<AllocatedType>::create_suballocator() {
        return this->template new_other_object<AllocatorHandle<ObjectType>>(this->resource());
    }
} // namespace nova::mem
<|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>
#include <vector>
#include "base/command_line.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "chrome/browser/chrome_browser_main.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/testing_pref_service.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/main_function_params.h"
#include "net/socket/client_socket_pool_base.h"
#include "testing/gtest/include/gtest/gtest.h"

class BrowserMainTest : public testing::Test {
 public:
  BrowserMainTest() : command_line_(CommandLine::NO_PROGRAM) {}

 protected:
  TestingPrefService pref_service_;
  CommandLine command_line_;
};

TEST_F(BrowserMainTest, WarmConnectionFieldTrial_WarmestSocket) {
  command_line_.AppendSwitchASCII(switches::kSocketReusePolicy, "0");

  scoped_ptr<content::MainFunctionParams> params(
      new content::MainFunctionParams(command_line_));
  scoped_ptr<content::BrowserMainParts> bw(
      content::GetContentClient()->browser()->CreateBrowserMainParts(*params));
  ChromeBrowserMainParts* cbw = static_cast<ChromeBrowserMainParts*>(bw.get());
  EXPECT_TRUE(cbw);
  if (cbw) {
    cbw->WarmConnectionFieldTrial();
    EXPECT_EQ(0, net::GetSocketReusePolicy());
  }
}

TEST_F(BrowserMainTest, WarmConnectionFieldTrial_Random) {
  scoped_ptr<content::MainFunctionParams> params(
      new content::MainFunctionParams(command_line_));
  scoped_ptr<content::BrowserMainParts> bw(
      content::GetContentClient()->browser()->CreateBrowserMainParts(*params));
  ChromeBrowserMainParts* cbw = static_cast<ChromeBrowserMainParts*>(bw.get());
  EXPECT_TRUE(cbw);
  if (cbw) {
    const int kNumRuns = 1000;
    for (int i = 0; i < kNumRuns; i++) {
      cbw->WarmConnectionFieldTrial();
      int val = net::GetSocketReusePolicy();
      EXPECT_LE(val, 2);
      EXPECT_GE(val, 0);
    }
  }
}

TEST_F(BrowserMainTest, WarmConnectionFieldTrial_Invalid) {
  command_line_.AppendSwitchASCII(switches::kSocketReusePolicy, "100");

  scoped_ptr<content::MainFunctionParams> params(
      new content::MainFunctionParams(command_line_));
  // This test ends up launching a new process, and that doesn't initialize the
  // ContentClient interfaces.
  scoped_ptr<content::BrowserMainParts> bw;
  if (content::GetContentClient()) {
    bw.reset(content::GetContentClient()->browser()->CreateBrowserMainParts(
        *params));
  } else {
    chrome::ChromeContentBrowserClient ccbc;
    bw.reset(ccbc.CreateBrowserMainParts(*params));
  }
  ChromeBrowserMainParts* cbw = static_cast<ChromeBrowserMainParts*>(bw.get());
  EXPECT_TRUE(cbw);
  if (cbw) {
#if defined(NDEBUG) && defined(DCHECK_ALWAYS_ON)
    EXPECT_DEATH(cbw->WarmConnectionFieldTrial(),
                 "Not a valid socket reuse policy group");
#else
    EXPECT_DEBUG_DEATH(cbw->WarmConnectionFieldTrial(),
                       "Not a valid socket reuse policy group");
#endif
  }
}
<commit_msg>Fix unit_tests compile eror in chrome_browser_main_unittest.cc for Android<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>
#include <vector>
#include "base/command_line.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "chrome/browser/chrome_browser_main.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/testing_pref_service.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/main_function_params.h"
#include "net/socket/client_socket_pool_base.h"
#include "testing/gtest/include/gtest/gtest.h"

class BrowserMainTest : public testing::Test {
 public:
  BrowserMainTest() : command_line_(CommandLine::NO_PROGRAM) {}

 protected:
  TestingPrefService pref_service_;
  CommandLine command_line_;
};

TEST_F(BrowserMainTest, WarmConnectionFieldTrial_WarmestSocket) {
  command_line_.AppendSwitchASCII(switches::kSocketReusePolicy, "0");

  scoped_ptr<content::MainFunctionParams> params(
      new content::MainFunctionParams(command_line_));
  scoped_ptr<content::BrowserMainParts> bw(
      content::GetContentClient()->browser()->CreateBrowserMainParts(*params));
  ChromeBrowserMainParts* cbw = static_cast<ChromeBrowserMainParts*>(bw.get());
  EXPECT_TRUE(cbw);
  if (cbw) {
    cbw->WarmConnectionFieldTrial();
    EXPECT_EQ(0, net::GetSocketReusePolicy());
  }
}

TEST_F(BrowserMainTest, WarmConnectionFieldTrial_Random) {
  scoped_ptr<content::MainFunctionParams> params(
      new content::MainFunctionParams(command_line_));
  scoped_ptr<content::BrowserMainParts> bw(
      content::GetContentClient()->browser()->CreateBrowserMainParts(*params));
  ChromeBrowserMainParts* cbw = static_cast<ChromeBrowserMainParts*>(bw.get());
  EXPECT_TRUE(cbw);
  if (cbw) {
    const int kNumRuns = 1000;
    for (int i = 0; i < kNumRuns; i++) {
      cbw->WarmConnectionFieldTrial();
      int val = net::GetSocketReusePolicy();
      EXPECT_LE(val, 2);
      EXPECT_GE(val, 0);
    }
  }
}
#if GTEST_HAS_DEATH_TEST
TEST_F(BrowserMainTest, WarmConnectionFieldTrial_Invalid) {
  command_line_.AppendSwitchASCII(switches::kSocketReusePolicy, "100");

  scoped_ptr<content::MainFunctionParams> params(
      new content::MainFunctionParams(command_line_));
  // This test ends up launching a new process, and that doesn't initialize the
  // ContentClient interfaces.
  scoped_ptr<content::BrowserMainParts> bw;
  if (content::GetContentClient()) {
    bw.reset(content::GetContentClient()->browser()->CreateBrowserMainParts(
        *params));
  } else {
    chrome::ChromeContentBrowserClient ccbc;
    bw.reset(ccbc.CreateBrowserMainParts(*params));
  }
  ChromeBrowserMainParts* cbw = static_cast<ChromeBrowserMainParts*>(bw.get());
  EXPECT_TRUE(cbw);
  if (cbw) {
#if defined(NDEBUG) && defined(DCHECK_ALWAYS_ON)
    EXPECT_DEATH(cbw->WarmConnectionFieldTrial(),
                 "Not a valid socket reuse policy group");
#else
    EXPECT_DEBUG_DEATH(cbw->WarmConnectionFieldTrial(),
                       "Not a valid socket reuse policy group");
#endif
  }
}
#endif
<|endoftext|>


<commit_before>// Copyright (c) 2016, Tom Honermann
//
// This file is distributed under the MIT License. See the accompanying file
// LICENSE.txt or http://www.opensource.org/licenses/mit-license.php for terms
// and conditions.

#ifndef TEXT_VIEW_ITEXT_SENTINEL_HPP // {
#define TEXT_VIEW_ITEXT_SENTINEL_HPP

#include <iterator>
#include <range/v3/range_traits.hpp>
#include <text_view_detail/concepts.hpp>
#include <text_view_detail/error_policy.hpp>
#include <text_view_detail/itext_iterator.hpp>

namespace std {
namespace experimental {
inline namespace text {

template<typename ET, typename VT, typename TEP = text_default_error_policy,
CONCEPT_REQUIRES_(
    TextEncoding<ET>(),
    ranges::View<VT>(),
    TextErrorPolicy<TEP>())>
class itext_sentinel {
public:
    using view_type = VT;
    using error_policy = TEP;
    using sentinel =
        ranges::sentinel_t<typename std::add_const<VT>::type>;

    itext_sentinel() = default;

    itext_sentinel(sentinel s)
        : s{s} {}

    friend bool operator==(
        const itext_iterator<ET, VT, TEP> &ti,
        const itext_sentinel &ts)
    {
        return ts.equal(ti);
    }
    friend bool operator!=(
        const itext_iterator<ET, VT, TEP> &ti,
        const itext_sentinel &ts)
    {
        return !(ti == ts);
    }
    friend bool operator==(
        const itext_sentinel &ts,
        const itext_iterator<ET, VT, TEP> &ti)
    {
        return ti == ts;
    }
    friend bool operator!=(
        const itext_sentinel &ts,
        const itext_iterator<ET, VT, TEP> &ti)
    {
        return !(ts == ti);
    }

    const sentinel& base() const noexcept {
        return s;
    }

private:
    CONCEPT_REQUIRES(
        ! ranges::ForwardIterator<
              decltype(std::declval<const itext_iterator<ET, VT>&>().base())>())
    bool equal(const itext_iterator<ET, VT, TEP> &ti) const {
        // For input iterators, the base iterator corresponds to the next input
        // to be decoded.  Naively checking for base comparison only therefore
        // results in premature matches when the last code point in the input
        // is consumed.  For this reason, base equality is only considered a
        // sentinel match if the iterator is not ok.  It is assumed that the
        // reason the base iterator is not ok is that an attempt was made to
        // decode a code point after the last one in the input.  This heuristic
        // can be defeated when an iterator is not ok for other reasons.
        return ti.base() == base()
            && ! ti.is_ok();
    }
    CONCEPT_REQUIRES(
        ranges::ForwardIterator<
              decltype(std::declval<const itext_iterator<ET, VT, TEP>&>().base())>())
    bool equal(const itext_iterator<ET, VT, TEP> &ti) const {
        return ti.base() == base();
    }

private:
    sentinel s;
};

} // inline namespace text
} // namespace experimental
} // namespace std

#endif // } TEXT_VIEW_ITEXT_SENTINEL_HPP
<commit_msg>range-v3 port: Merge ../text_view<commit_after>// Copyright (c) 2016, Tom Honermann
//
// This file is distributed under the MIT License. See the accompanying file
// LICENSE.txt or http://www.opensource.org/licenses/mit-license.php for terms
// and conditions.

#ifndef TEXT_VIEW_ITEXT_SENTINEL_HPP // {
#define TEXT_VIEW_ITEXT_SENTINEL_HPP

#include <iterator>
#include <range/v3/range_traits.hpp>
#include <text_view_detail/concepts.hpp>
#include <text_view_detail/error_policy.hpp>
#include <text_view_detail/itext_iterator.hpp>

namespace std {
namespace experimental {
inline namespace text {

template<typename ET, typename VT, typename TEP = text_default_error_policy,
CONCEPT_REQUIRES_(
    TextEncoding<ET>(),
    ranges::View<VT>(),
    TextErrorPolicy<TEP>())>
class itext_sentinel {
public:
    using view_type = VT;
    using error_policy = TEP;
    using sentinel =
        ranges::sentinel_t<typename std::add_const<VT>::type>;

    itext_sentinel() = default;

    itext_sentinel(sentinel s)
        : s(std::move(s)) {}

    friend bool operator==(
        const itext_iterator<ET, VT, TEP> &ti,
        const itext_sentinel &ts)
    {
        return ts.equal(ti);
    }
    friend bool operator!=(
        const itext_iterator<ET, VT, TEP> &ti,
        const itext_sentinel &ts)
    {
        return !(ti == ts);
    }
    friend bool operator==(
        const itext_sentinel &ts,
        const itext_iterator<ET, VT, TEP> &ti)
    {
        return ti == ts;
    }
    friend bool operator!=(
        const itext_sentinel &ts,
        const itext_iterator<ET, VT, TEP> &ti)
    {
        return !(ts == ti);
    }

    const sentinel& base() const noexcept {
        return s;
    }

private:
    CONCEPT_REQUIRES(
        ! ranges::ForwardIterator<
              decltype(std::declval<const itext_iterator<ET, VT>&>().base())>())
    bool equal(const itext_iterator<ET, VT, TEP> &ti) const {
        // For input iterators, the base iterator corresponds to the next input
        // to be decoded.  Naively checking for base comparison only therefore
        // results in premature matches when the last code point in the input
        // is consumed.  For this reason, base equality is only considered a
        // sentinel match if the iterator is not ok.  It is assumed that the
        // reason the base iterator is not ok is that an attempt was made to
        // decode a code point after the last one in the input.  This heuristic
        // can be defeated when an iterator is not ok for other reasons.
        return ti.base() == base()
            && ! ti.is_ok();
    }
    CONCEPT_REQUIRES(
        ranges::ForwardIterator<
              decltype(std::declval<const itext_iterator<ET, VT, TEP>&>().base())>())
    bool equal(const itext_iterator<ET, VT, TEP> &ti) const {
        return ti.base() == base();
    }

private:
    sentinel s;
};

} // inline namespace text
} // namespace experimental
} // namespace std

#endif // } TEXT_VIEW_ITEXT_SENTINEL_HPP
<|endoftext|>


<commit_before>// This file is distributed under the MIT license.
// See the LICENSE file for details.

#include <cstddef>
#include <type_traits>
#include <utility>

#include <visionaray/math/limits.h>
#include <visionaray/math/matrix.h>
#include <visionaray/intersector.h>
#include <visionaray/update_if.h>

#include "../exit_traversal.h"
#include "../stack.h"
#include "../tags.h"
#include "../traversal_result.h"
#include "hit_record.h"

namespace visionaray
{

//-------------------------------------------------------------------------------------------------
// Ray / BVH intersection
//

template <
    detail::traversal_type Traversal,
    size_t MultiHitMax = 1,             // Max hits for multi-hit traversal
    typename R,
    typename BVH,
    typename = typename std::enable_if<is_any_bvh<BVH>::value>::type,
    typename = typename std::enable_if<!is_any_bvh_inst<BVH>::value>::type,
    typename Intersector,
    typename T = typename R::scalar_type,
    typename Cond = is_closer_t
    >
VSNRAY_FUNC
inline auto intersect(
        R const&     ray,
        BVH const&   b,
        Intersector& isect,
        T            max_t = numeric_limits<T>::max(),
        Cond         update_cond = Cond()
        )
    -> typename detail::traversal_result< hit_record_bvh<
            R,
            decltype( isect(ray, std::declval<typename BVH::primitive_type>()) )
            >, Traversal, MultiHitMax>::type
{

    using namespace detail;
    using HR = hit_record_bvh<R, decltype(isect(ray, std::declval<typename BVH::primitive_type>()))>;

    using RT = typename detail::traversal_result<HR, Traversal, MultiHitMax>::type;

    RT result;

    stack<32> st;
    st.push(0); // address of root node

    auto inv_dir = T(1.0) / ray.dir;

    // while ray not terminated
next:
    while (!st.empty())
    {
        auto node = b.node(st.pop());

        // while node does not contain primitives
        //     traverse to the next node

        while (!is_leaf(node))
        {
            auto children = &b.node(node.get_child(0));

            auto hr1 = isect(ray, children[0].get_bounds(), inv_dir);
            auto hr2 = isect(ray, children[1].get_bounds(), inv_dir);

            auto b1 = any( is_closer(hr1, result, max_t) );
            auto b2 = any( is_closer(hr2, result, max_t) );

            if (b1 && b2)
            {
                unsigned near_addr = all( hr1.tnear < hr2.tnear ) ? 0 : 1;
                st.push(node.get_child(!near_addr));
                node = b.node(node.get_child(near_addr));
            }
            else if (b1)
            {
                node = b.node(node.get_child(0));
            }
            else if (b2)
            {
                node = b.node(node.get_child(1));
            }
            else
            {
                goto next;
            }
        }

        // while node contains untested primitives
        //     perform a ray-primitive intersection test

        for (auto i = node.get_indices().first; i != node.get_indices().last; ++i)
        {
            auto prim = b.primitive(i);

            auto hr = HR(isect(ray, prim), i);
            auto closer = update_cond(hr, result, max_t);

#ifndef __CUDA_ARCH__
            if (!any(closer))
            {
                continue;
            }
#endif

            update_if(result, hr, closer);

            exit_traversal<Traversal> early_exit;
            if (early_exit.check(result))
            {
                return result;
            }
        }
    }

    return result;

}

// Overload for instances ---------------------------------

template <
    detail::traversal_type Traversal,
    size_t MultiHitMax = 1,             // Max hits for multi-hit traversal
    typename R,
    typename BVH,
    typename = typename std::enable_if<is_any_bvh_inst<BVH>::value>::type,
    typename Intersector,
    typename T = typename R::scalar_type,
    typename Cond = is_closer_t
    >
VSNRAY_FUNC
inline auto intersect(
        R const&     ray,
        BVH const&   b,
        Intersector& isect,
        T            max_t = numeric_limits<T>::max(),
        Cond         update_cond = Cond()
        )
    -> typename detail::traversal_result< hit_record_bvh_inst<
            R,
            decltype( isect(ray, std::declval<typename BVH::primitive_type>()) )
            >, Traversal, MultiHitMax>::type
{
    using namespace detail;
    using HR = hit_record_bvh_inst<R, decltype(isect(ray, std::declval<typename BVH::primitive_type>()))>;

    using RT = typename detail::traversal_result<HR, Traversal, MultiHitMax>::type;

    R transformed_ray = ray;
    transformed_ray.ori = (matrix<4, 4, T>(b.transform_inv()) * vector<4, T>(ray.ori, T(1.0))).xyz();
    transformed_ray.dir = (matrix<4, 4, T>(b.transform_inv()) * vector<4, T>(ray.dir, T(0.0))).xyz();
    // NOTE: dir is in general *not* normalized!

    auto hr = intersect<Traversal, MultiHitMax>(
            transformed_ray,
            b.get_ref(),
            isect,
            max_t,
            update_cond
            );

    return RT(hr, hr.primitive_list_index, matrix<4, 4, T>(b.transform_inv()));
}

//-------------------------------------------------------------------------------------------------
// Default intersect returns closest hit!
//

// overload w/ custom intersector -------------------------

template <
    typename R,
    typename BVH,
    typename = typename std::enable_if<is_any_bvh<BVH>::value>::type,
    typename Intersector,
    typename Cond = is_closer_t
    >
VSNRAY_FUNC
inline auto intersect(
        R const&     ray,
        BVH const&   b,
        Intersector& isect,
        Cond         update_cond = Cond()
        )
    -> decltype(intersect<detail::ClosestHit>(ray, b, isect, numeric_limits<typename R::scalar_type>::max(), update_cond))
{
    return intersect<detail::ClosestHit>(ray, b, isect, numeric_limits<typename R::scalar_type>::max(), update_cond);
}

// overload w/ default intersector ------------------------

template <
    typename R,
    typename BVH,
    typename = typename std::enable_if<is_any_bvh<BVH>::value>::type,
    typename Cond = is_closer_t
    >
VSNRAY_FUNC
inline auto intersect(
        R const&   ray,
        BVH const& b,
        Cond       update_cond = Cond()
        )
    -> decltype(intersect<detail::ClosestHit>(
            ray,
            b,
            std::declval<default_intersector&>(), numeric_limits<typename R::scalar_type>::max(), update_cond)
            )
{
    default_intersector isect;
    return intersect<detail::ClosestHit>(ray, b, isect, numeric_limits<typename R::scalar_type>::max(), update_cond);
}

} // visionaray
<commit_msg>Add experimental short stack traversal code<commit_after>// This file is distributed under the MIT license.
// See the LICENSE file for details.

#include <cstddef>
#include <type_traits>
#include <utility>

#include <visionaray/math/limits.h>
#include <visionaray/math/matrix.h>
#include <visionaray/intersector.h>
#include <visionaray/update_if.h>

#include "../exit_traversal.h"
#include "../stack.h"
#include "../tags.h"
#include "../traversal_result.h"
#include "hit_record.h"

namespace visionaray
{

//-------------------------------------------------------------------------------------------------
// Ray / BVH intersection
//

template <
    detail::traversal_type Traversal,
    size_t MultiHitMax = 1,             // Max hits for multi-hit traversal
    typename R,
    typename BVH,
    typename = typename std::enable_if<is_any_bvh<BVH>::value>::type,
    typename = typename std::enable_if<!is_any_bvh_inst<BVH>::value>::type,
    typename Intersector,
    typename T = typename R::scalar_type,
    typename Cond = is_closer_t
    >
VSNRAY_FUNC
inline auto intersect(
        R const&     ray,
        BVH const&   b,
        Intersector& isect,
        T            max_t = numeric_limits<T>::max(),
        Cond         update_cond = Cond()
        )
    -> typename detail::traversal_result< hit_record_bvh<
            R,
            decltype( isect(ray, std::declval<typename BVH::primitive_type>()) )
            >, Traversal, MultiHitMax>::type
{
#if 1
    using namespace detail;
    using HR = hit_record_bvh<R, decltype(isect(ray, std::declval<typename BVH::primitive_type>()))>;

    using RT = typename detail::traversal_result<HR, Traversal, MultiHitMax>::type;

    RT result;

    stack<32> st;
    st.push(0); // address of root node

    auto inv_dir = T(1.0) / ray.dir;

    // while ray not terminated
next:
    while (!st.empty())
    {
        auto node = b.node(st.pop());

        // while node does not contain primitives
        //     traverse to the next node

        while (!is_leaf(node))
        {
            auto children = &b.node(node.get_child(0));

            auto hr1 = isect(ray, children[0].get_bounds(), inv_dir);
            auto hr2 = isect(ray, children[1].get_bounds(), inv_dir);

            auto b1 = any( is_closer(hr1, result, max_t) );
            auto b2 = any( is_closer(hr2, result, max_t) );

            if (b1 && b2)
            {
                unsigned near_addr = all( hr1.tnear < hr2.tnear ) ? 0 : 1;
                st.push(node.get_child(!near_addr));
                node = b.node(node.get_child(near_addr));
            }
            else if (b1)
            {
                node = b.node(node.get_child(0));
            }
            else if (b2)
            {
                node = b.node(node.get_child(1));
            }
            else
            {
                goto next;
            }
        }

        // while node contains untested primitives
        //     perform a ray-primitive intersection test

        for (auto i = node.get_indices().first; i != node.get_indices().last; ++i)
        {
            auto prim = b.primitive(i);

            auto hr = HR(isect(ray, prim), i);
            auto closer = update_cond(hr, result, max_t);

#ifndef __CUDA_ARCH__
            if (!any(closer))
            {
                continue;
            }
#endif

            update_if(result, hr, closer);

            exit_traversal<Traversal> early_exit;
            if (early_exit.check(result))
            {
                return result;
            }
        }
    }

    return result;
#else
    using namespace detail;
    using HR = hit_record_bvh<R, decltype(isect(ray, std::declval<typename BVH::primitive_type>()))>;

    using RT = typename detail::traversal_result<HR, Traversal, MultiHitMax>::type;

    RT result;

    auto inv_dir = T(1.0) / ray.dir;

    bvh_node node = b.node(0);

    uint64_t level = 0x8000000000000000ULL;

    uint64_t pop_level = -1;

    uint64_t trail = 0;

    unsigned st1 = -1;
    unsigned st2 = -1;
    unsigned st3 = -1;
    unsigned st4 = -1;
    unsigned st5 = -1;

    auto push_st = [&](unsigned n)
    {
        st1 = st2;
        st2 = st3;
        st3 = st4;
        st4 = st5;
        st5 = n;
    };

    auto pop_st = [&]()
    {
        unsigned res = st5;
        st5 = st4;
        st4 = st3;
        st3 = st2;
        st2 = st1;
        st1 = unsigned(-1);
        return res;
    };

    auto empty_st = [&st5]()
    {
        return st5 == unsigned(-1);
    };

    auto push = [&](unsigned n)
    {
        return push_st(n);
    };

    auto pop = [&]()
        -> bool
    {
        trail &= -level;
        trail += level;

        uint64_t temp = trail >> 1;
        level = ((temp - 1) ^ temp) + 1;

        if (trail & 0x8000000000000000ULL)
        {
            return true;
        }

        pop_level = level;

        if (empty_st())
        {
            node = b.node(0);
            level = 0x8000000000000000ULL;
        }
        else
        {
            node = b.node(pop_st());
        }

        return false;
    };

    while (true)
    {
        while (!is_leaf(node))
        {
            auto children = &b.node(node.get_child(0));

            auto hr1 = isect(ray, children[0].get_bounds(), inv_dir);
            auto hr2 = isect(ray, children[1].get_bounds(), inv_dir);

            auto b1 = any( is_closer(hr1, result, max_t) );
            auto b2 = any( is_closer(hr2, result, max_t) );

            if (b1 && b2)
            {
                unsigned near_addr = all( hr1.tnear < hr2.tnear ) ? 0 : 1;
                unsigned far_addr = !near_addr;
                level >>= 1;
                if ((trail & level) != 0)
                {
                    node = b.node(node.get_child(far_addr));
                }
                else
                {
                    push(node.get_child(far_addr));
                    node = b.node(node.get_child(near_addr));
                }
            }
            else if (b1 || b2)
            {
                level >>= 1;
                if (level != pop_level)
                {
                    trail |= level;
                    node = b1 ? b.node(node.get_child(0)) : b.node(node.get_child(1));
                }
                else
                {
                    bool end_traversal = pop();
                    if (end_traversal)
                    {
                        return result;
                    }
                }
            }
            else
            {
                bool end_traversal = pop();
                if (end_traversal)
                {
                    return result;
                }
            }
        }

        // while node contains untested primitives
        //     perform a ray-primitive intersection test

        for (auto i = node.get_indices().first; i != node.get_indices().last; ++i)
        {
            auto prim = b.primitive(i);

            auto hr = HR(isect(ray, prim), i);
            auto closer = update_cond(hr, result, max_t);

#ifndef __CUDA_ARCH__
            if (!any(closer))
            {
                continue;
            }
#endif

            update_if(result, hr, closer);

            exit_traversal<Traversal> early_exit;
            if (early_exit.check(result))
            {
                return result;
            }
        }

        bool end_traversal = pop();
        if (end_traversal)
        {
            return result;
        }
    }

    return result;
#endif
}

// Overload for instances ---------------------------------

template <
    detail::traversal_type Traversal,
    size_t MultiHitMax = 1,             // Max hits for multi-hit traversal
    typename R,
    typename BVH,
    typename = typename std::enable_if<is_any_bvh_inst<BVH>::value>::type,
    typename Intersector,
    typename T = typename R::scalar_type,
    typename Cond = is_closer_t
    >
VSNRAY_FUNC
inline auto intersect(
        R const&     ray,
        BVH const&   b,
        Intersector& isect,
        T            max_t = numeric_limits<T>::max(),
        Cond         update_cond = Cond()
        )
    -> typename detail::traversal_result< hit_record_bvh_inst<
            R,
            decltype( isect(ray, std::declval<typename BVH::primitive_type>()) )
            >, Traversal, MultiHitMax>::type
{
    using namespace detail;
    using HR = hit_record_bvh_inst<R, decltype(isect(ray, std::declval<typename BVH::primitive_type>()))>;

    using RT = typename detail::traversal_result<HR, Traversal, MultiHitMax>::type;

    R transformed_ray = ray;
    transformed_ray.ori = (matrix<4, 4, T>(b.transform_inv()) * vector<4, T>(ray.ori, T(1.0))).xyz();
    transformed_ray.dir = (matrix<4, 4, T>(b.transform_inv()) * vector<4, T>(ray.dir, T(0.0))).xyz();
    // NOTE: dir is in general *not* normalized!

    auto hr = intersect<Traversal, MultiHitMax>(
            transformed_ray,
            b.get_ref(),
            isect,
            max_t,
            update_cond
            );

    return RT(hr, hr.primitive_list_index, matrix<4, 4, T>(b.transform_inv()));
}

//-------------------------------------------------------------------------------------------------
// Default intersect returns closest hit!
//

// overload w/ custom intersector -------------------------

template <
    typename R,
    typename BVH,
    typename = typename std::enable_if<is_any_bvh<BVH>::value>::type,
    typename Intersector,
    typename Cond = is_closer_t
    >
VSNRAY_FUNC
inline auto intersect(
        R const&     ray,
        BVH const&   b,
        Intersector& isect,
        Cond         update_cond = Cond()
        )
    -> decltype(intersect<detail::ClosestHit>(ray, b, isect, numeric_limits<typename R::scalar_type>::max(), update_cond))
{
    return intersect<detail::ClosestHit>(ray, b, isect, numeric_limits<typename R::scalar_type>::max(), update_cond);
}

// overload w/ default intersector ------------------------

template <
    typename R,
    typename BVH,
    typename = typename std::enable_if<is_any_bvh<BVH>::value>::type,
    typename Cond = is_closer_t
    >
VSNRAY_FUNC
inline auto intersect(
        R const&   ray,
        BVH const& b,
        Cond       update_cond = Cond()
        )
    -> decltype(intersect<detail::ClosestHit>(
            ray,
            b,
            std::declval<default_intersector&>(), numeric_limits<typename R::scalar_type>::max(), update_cond)
            )
{
    default_intersector isect;
    return intersect<detail::ClosestHit>(ray, b, isect, numeric_limits<typename R::scalar_type>::max(), update_cond);
}

} // visionaray
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <set>
#include <string>

#include "chrome/browser/download/download_extensions.h"

#include "base/string_util.h"
#include "net/base/mime_util.h"
#include "net/base/net_util.h"

namespace download_util {

// For file extensions taken from mozilla:

/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Mozilla Communicator client code, released
 * March 31, 1998.
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-1999
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Doug Turner <dougt@netscape.com>
 *   Dean Tessman <dean_tessman@hotmail.com>
 *   Brodie Thiesfield <brofield@jellycan.com>
 *   Jungshik Shin <jshin@i18nl10n.com>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either of the GNU General Public License Version 2 or later (the "GPL"),
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

static const struct Executables {
    const char* extension;
    DownloadDangerLevel level;
} g_executables[] = {
  { "class", AllowOnUserGesture },
  { "htm", AllowOnUserGesture },
  { "html", AllowOnUserGesture },
  { "jar", AllowOnUserGesture },
  { "jnlp", AllowOnUserGesture },
  { "pdf", AllowOnUserGesture },
  { "pdfxml", AllowOnUserGesture },
  { "mars", AllowOnUserGesture },
  { "fdf", AllowOnUserGesture },
  { "xfdf", AllowOnUserGesture },
  { "xdp", AllowOnUserGesture },
  { "xfd", AllowOnUserGesture },
  { "pl", AllowOnUserGesture },
  { "py", AllowOnUserGesture },
  { "rb", AllowOnUserGesture },
  { "shtm", AllowOnUserGesture },
  { "shtml", AllowOnUserGesture },
  { "svg", AllowOnUserGesture },
  { "swf", AllowOnUserGesture },
  { "xht", AllowOnUserGesture },
  { "xhtm", AllowOnUserGesture },
  { "xhtml", AllowOnUserGesture },
  { "xml", AllowOnUserGesture },
  { "xsl", AllowOnUserGesture },
  { "xslt", AllowOnUserGesture },
#if defined(OS_WIN)
  { "ad", AllowOnUserGesture },
  { "ade", AllowOnUserGesture },
  { "adp", AllowOnUserGesture },
  { "app", AllowOnUserGesture },
  { "application", AllowOnUserGesture },
  { "asp", AllowOnUserGesture },
  { "asx", AllowOnUserGesture },
  { "bas", AllowOnUserGesture },
  { "bat", AllowOnUserGesture },
  { "chi", AllowOnUserGesture },
  { "chm", AllowOnUserGesture },
  { "cmd", AllowOnUserGesture },
  { "com", AllowOnUserGesture },
  { "cpl", AllowOnUserGesture },
  { "crt", AllowOnUserGesture },
  { "dll", Dangerous },
  { "drv", Dangerous },
  { "exe", AllowOnUserGesture },
  { "fxp", AllowOnUserGesture },
  { "hlp", AllowOnUserGesture },
  { "hta", AllowOnUserGesture },
  { "htt", AllowOnUserGesture },
  { "inf", AllowOnUserGesture },
  { "ins", AllowOnUserGesture },
  { "isp", AllowOnUserGesture },
  { "js", AllowOnUserGesture },
  { "jse", AllowOnUserGesture },
  { "lnk", AllowOnUserGesture },
  { "mad", AllowOnUserGesture },
  { "maf", AllowOnUserGesture },
  { "mag", AllowOnUserGesture },
  { "mam", AllowOnUserGesture },
  { "maq", AllowOnUserGesture },
  { "mar", AllowOnUserGesture },
  { "mas", AllowOnUserGesture },
  { "mat", AllowOnUserGesture },
  { "mau", AllowOnUserGesture },
  { "mav", AllowOnUserGesture },
  { "maw", AllowOnUserGesture },
  { "mda", AllowOnUserGesture },
  { "mdb", AllowOnUserGesture },
  { "mde", AllowOnUserGesture },
  { "mdt", AllowOnUserGesture },
  { "mdw", AllowOnUserGesture },
  { "mdz", AllowOnUserGesture },
  { "mht", AllowOnUserGesture },
  { "mhtml", AllowOnUserGesture },
  { "mmc", AllowOnUserGesture },
  { "msc", AllowOnUserGesture },
  { "msh", AllowOnUserGesture },
  { "mshxml", AllowOnUserGesture },
  { "msi", AllowOnUserGesture },
  { "msp", AllowOnUserGesture },
  { "mst", AllowOnUserGesture },
  { "ocx", AllowOnUserGesture },
  { "ops", AllowOnUserGesture },
  { "pcd", AllowOnUserGesture },
  { "pif", AllowOnUserGesture },
  { "plg", AllowOnUserGesture },
  { "prf", AllowOnUserGesture },
  { "prg", AllowOnUserGesture },
  { "pst", AllowOnUserGesture },
  { "reg", AllowOnUserGesture },
  { "scf", AllowOnUserGesture },
  { "scr", AllowOnUserGesture },
  { "sct", AllowOnUserGesture },
  { "shb", AllowOnUserGesture },
  { "shs", AllowOnUserGesture },
  { "sys", Dangerous },
  { "url", AllowOnUserGesture },
  { "vb", AllowOnUserGesture },
  { "vbe", AllowOnUserGesture },
  { "vbs", AllowOnUserGesture },
  { "vsd", AllowOnUserGesture },
  { "vsmacros", AllowOnUserGesture },
  { "vss", AllowOnUserGesture },
  { "vst", AllowOnUserGesture },
  { "vsw", AllowOnUserGesture },
  { "ws", AllowOnUserGesture },
  { "wsc", AllowOnUserGesture },
  { "wsf", AllowOnUserGesture },
  { "wsh", AllowOnUserGesture },
  { "xbap", Dangerous },
#elif defined(OS_MACOSX)
  // TODO(thakis): Figure out what makes sense here -- crbug.com/19096
  { "app", AllowOnUserGesture },
  { "dmg", AllowOnUserGesture },
#elif defined(OS_POSIX)
  // TODO(estade): lengthen this list.
  { "bash", AllowOnUserGesture },
  { "csh", AllowOnUserGesture },
  { "deb", AllowOnUserGesture },
  { "exe", AllowOnUserGesture },
  { "ksh", AllowOnUserGesture },
  { "rpm", AllowOnUserGesture },
  { "sh", AllowOnUserGesture },
  { "tcsh", AllowOnUserGesture },
#endif
};

DownloadDangerLevel GetFileDangerLevel(const FilePath& path) {
  return GetFileExtensionDangerLevel(path.Extension());
}

DownloadDangerLevel GetFileExtensionDangerLevel(
    const FilePath::StringType& extension) {
  if (extension.empty())
    return NotDangerous;
  if (!IsStringASCII(extension))
    return NotDangerous;
#if defined(OS_WIN)
  std::string ascii_extension = WideToASCII(extension);
#elif defined(OS_POSIX)
  std::string ascii_extension = extension;
#endif

  // Strip out leading dot if it's still there
  if (ascii_extension[0] == FilePath::kExtensionSeparator)
    ascii_extension.erase(0, 1);

  for (size_t i = 0; i < arraysize(g_executables); ++i) {
    if (LowerCaseEqualsASCII(ascii_extension, g_executables[i].extension))
      return g_executables[i].level;
  }
  return NotDangerous;
}

bool IsFileExtensionSafe(const FilePath::StringType& extension) {
  return GetFileExtensionDangerLevel(extension) == NotDangerous;
}

bool IsFileSafe(const FilePath& path) {
  return GetFileDangerLevel(path) == NotDangerous;
}

static const char* kExecutableWhiteList[] = {
  // JavaScript is just as powerful as EXE.
  "text/javascript",
  "text/javascript;version=*",
  "text/html",
  // Registry files can cause critical changes to the MS OS behavior.
  // Addition of this mimetype also addresses bug 7337.
  "text/x-registry",
  "text/x-sh",
  // Some sites use binary/octet-stream to mean application/octet-stream.
  // See http://code.google.com/p/chromium/issues/detail?id=1573
  "binary/octet-stream"
};

static const char* kExecutableBlackList[] = {
  // These application types are not executable.
  "application/*+xml",
  "application/xml"
};

bool IsExecutableMimeType(const std::string& mime_type) {
  for (size_t i = 0; i < arraysize(kExecutableWhiteList); ++i) {
    if (net::MatchesMimeType(kExecutableWhiteList[i], mime_type))
      return true;
  }
  for (size_t i = 0; i < arraysize(kExecutableBlackList); ++i) {
    if (net::MatchesMimeType(kExecutableBlackList[i], mime_type))
      return false;
  }
  // We consider only other application types to be executable.
  return net::MatchesMimeType("application/*", mime_type);
}

}  // namespace download_util
<commit_msg>Tweak dangerous list based on (hopefully) final round of discussions. I think we have the balance about right now.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <set>
#include <string>

#include "chrome/browser/download/download_extensions.h"

#include "base/string_util.h"
#include "net/base/mime_util.h"
#include "net/base/net_util.h"

namespace download_util {

// For file extensions taken from mozilla:

/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Mozilla Communicator client code, released
 * March 31, 1998.
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998-1999
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Doug Turner <dougt@netscape.com>
 *   Dean Tessman <dean_tessman@hotmail.com>
 *   Brodie Thiesfield <brofield@jellycan.com>
 *   Jungshik Shin <jshin@i18nl10n.com>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either of the GNU General Public License Version 2 or later (the "GPL"),
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

static const struct Executables {
    const char* extension;
    DownloadDangerLevel level;
} g_executables[] = {
  { "class", Dangerous },
  { "htm", AllowOnUserGesture },
  { "html", AllowOnUserGesture },
  { "jar", Dangerous },
  { "jnlp", Dangerous },
  { "pdf", AllowOnUserGesture },
  { "pdfxml", AllowOnUserGesture },
  { "mars", AllowOnUserGesture },
  { "fdf", AllowOnUserGesture },
  { "xfdf", AllowOnUserGesture },
  { "xdp", AllowOnUserGesture },
  { "xfd", AllowOnUserGesture },
  { "pl", AllowOnUserGesture },
  { "py", AllowOnUserGesture },
  { "rb", AllowOnUserGesture },
  { "shtm", AllowOnUserGesture },
  { "shtml", AllowOnUserGesture },
  { "svg", AllowOnUserGesture },
  { "swf", AllowOnUserGesture },
  { "xht", AllowOnUserGesture },
  { "xhtm", AllowOnUserGesture },
  { "xhtml", AllowOnUserGesture },
  { "xml", AllowOnUserGesture },
  { "xsl", AllowOnUserGesture },
  { "xslt", AllowOnUserGesture },
#if defined(OS_WIN)
  { "ad", AllowOnUserGesture },
  { "ade", AllowOnUserGesture },
  { "adp", AllowOnUserGesture },
  { "app", AllowOnUserGesture },
  { "application", AllowOnUserGesture },
  { "asp", AllowOnUserGesture },
  { "asx", AllowOnUserGesture },
  { "bas", AllowOnUserGesture },
  { "bat", AllowOnUserGesture },
  { "chi", AllowOnUserGesture },
  { "chm", AllowOnUserGesture },
  { "cmd", AllowOnUserGesture },
  { "com", AllowOnUserGesture },
  { "cpl", AllowOnUserGesture },
  { "crt", AllowOnUserGesture },
  { "dll", Dangerous },
  { "drv", Dangerous },
  { "exe", AllowOnUserGesture },
  { "fxp", AllowOnUserGesture },
  { "hlp", AllowOnUserGesture },
  { "hta", AllowOnUserGesture },
  { "htt", AllowOnUserGesture },
  { "inf", AllowOnUserGesture },
  { "ins", AllowOnUserGesture },
  { "isp", AllowOnUserGesture },
  { "js", AllowOnUserGesture },
  { "jse", AllowOnUserGesture },
  { "lnk", AllowOnUserGesture },
  { "mad", AllowOnUserGesture },
  { "maf", AllowOnUserGesture },
  { "mag", AllowOnUserGesture },
  { "mam", AllowOnUserGesture },
  { "maq", AllowOnUserGesture },
  { "mar", AllowOnUserGesture },
  { "mas", AllowOnUserGesture },
  { "mat", AllowOnUserGesture },
  { "mau", AllowOnUserGesture },
  { "mav", AllowOnUserGesture },
  { "maw", AllowOnUserGesture },
  { "mda", AllowOnUserGesture },
  { "mdb", AllowOnUserGesture },
  { "mde", AllowOnUserGesture },
  { "mdt", AllowOnUserGesture },
  { "mdw", AllowOnUserGesture },
  { "mdz", AllowOnUserGesture },
  { "mht", AllowOnUserGesture },
  { "mhtml", AllowOnUserGesture },
  { "mmc", AllowOnUserGesture },
  { "msc", AllowOnUserGesture },
  { "msh", AllowOnUserGesture },
  { "mshxml", AllowOnUserGesture },
  { "msi", AllowOnUserGesture },
  { "msp", AllowOnUserGesture },
  { "mst", AllowOnUserGesture },
  { "ocx", AllowOnUserGesture },
  { "ops", AllowOnUserGesture },
  { "pcd", AllowOnUserGesture },
  { "pif", AllowOnUserGesture },
  { "plg", AllowOnUserGesture },
  { "prf", AllowOnUserGesture },
  { "prg", AllowOnUserGesture },
  { "pst", AllowOnUserGesture },
  { "reg", AllowOnUserGesture },
  { "scf", AllowOnUserGesture },
  { "scr", AllowOnUserGesture },
  { "sct", AllowOnUserGesture },
  { "shb", AllowOnUserGesture },
  { "shs", AllowOnUserGesture },
  { "sys", Dangerous },
  { "url", AllowOnUserGesture },
  { "vb", AllowOnUserGesture },
  { "vbe", AllowOnUserGesture },
  { "vbs", AllowOnUserGesture },
  { "vsd", AllowOnUserGesture },
  { "vsmacros", AllowOnUserGesture },
  { "vss", AllowOnUserGesture },
  { "vst", AllowOnUserGesture },
  { "vsw", AllowOnUserGesture },
  { "ws", AllowOnUserGesture },
  { "wsc", AllowOnUserGesture },
  { "wsf", AllowOnUserGesture },
  { "wsh", AllowOnUserGesture },
  { "xbap", Dangerous },
#elif defined(OS_MACOSX)
  // TODO(thakis): Figure out what makes sense here -- crbug.com/19096
  { "app", AllowOnUserGesture },
  { "dmg", AllowOnUserGesture },
#elif defined(OS_POSIX)
  // TODO(estade): lengthen this list.
  { "bash", AllowOnUserGesture },
  { "csh", AllowOnUserGesture },
  { "deb", AllowOnUserGesture },
  { "exe", AllowOnUserGesture },
  { "ksh", AllowOnUserGesture },
  { "rpm", AllowOnUserGesture },
  { "sh", AllowOnUserGesture },
  { "tcsh", AllowOnUserGesture },
#endif
};

DownloadDangerLevel GetFileDangerLevel(const FilePath& path) {
  return GetFileExtensionDangerLevel(path.Extension());
}

DownloadDangerLevel GetFileExtensionDangerLevel(
    const FilePath::StringType& extension) {
  if (extension.empty())
    return NotDangerous;
  if (!IsStringASCII(extension))
    return NotDangerous;
#if defined(OS_WIN)
  std::string ascii_extension = WideToASCII(extension);
#elif defined(OS_POSIX)
  std::string ascii_extension = extension;
#endif

  // Strip out leading dot if it's still there
  if (ascii_extension[0] == FilePath::kExtensionSeparator)
    ascii_extension.erase(0, 1);

  for (size_t i = 0; i < arraysize(g_executables); ++i) {
    if (LowerCaseEqualsASCII(ascii_extension, g_executables[i].extension))
      return g_executables[i].level;
  }
  return NotDangerous;
}

bool IsFileExtensionSafe(const FilePath::StringType& extension) {
  return GetFileExtensionDangerLevel(extension) == NotDangerous;
}

bool IsFileSafe(const FilePath& path) {
  return GetFileDangerLevel(path) == NotDangerous;
}

static const char* kExecutableWhiteList[] = {
  // JavaScript is just as powerful as EXE.
  "text/javascript",
  "text/javascript;version=*",
  "text/html",
  // Registry files can cause critical changes to the MS OS behavior.
  // Addition of this mimetype also addresses bug 7337.
  "text/x-registry",
  "text/x-sh",
  // Some sites use binary/octet-stream to mean application/octet-stream.
  // See http://code.google.com/p/chromium/issues/detail?id=1573
  "binary/octet-stream"
};

static const char* kExecutableBlackList[] = {
  // These application types are not executable.
  "application/*+xml",
  "application/xml"
};

bool IsExecutableMimeType(const std::string& mime_type) {
  for (size_t i = 0; i < arraysize(kExecutableWhiteList); ++i) {
    if (net::MatchesMimeType(kExecutableWhiteList[i], mime_type))
      return true;
  }
  for (size_t i = 0; i < arraysize(kExecutableBlackList); ++i) {
    if (net::MatchesMimeType(kExecutableBlackList[i], mime_type))
      return false;
  }
  // We consider only other application types to be executable.
  return net::MatchesMimeType("application/*", mime_type);
}

}  // namespace download_util
<|endoftext|>