<commit_before>/*
Copyright (C) 2007 <SWGEmu>
This File is part of Core3.
This program is free software; you can redistribute
it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software
Foundation; either version 2 of the License,
or (at your option) any later version.

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

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

Linking Engine3 statically or dynamically with other modules
is making a combined work based on Engine3.
Thus, the terms and conditions of the GNU Lesser General Public License
cover the whole combination.

In addition, as a special exception, the copyright holders of Engine3
give you permission to combine Engine3 program with free software
programs or libraries that are released under the GNU LGPL and with
code included in the standard release of Core3 under the GNU LGPL
license (or modified versions of such code, with unchanged license).
You may copy and distribute such a system following the terms of the
GNU LGPL for Engine3 and the licenses of the other code concerned,
provided that you include the source code of that other code when
and as the GNU LGPL requires distribution of source code.

Note that people who make modified versions of Engine3 are not obligated
to grant this special exception for their modified versions;
it is their choice whether to do so. The GNU Lesser General Public License
gives permission to release a modified version without this exception;
this exception also makes it possible to release a modified version
which carries forward this exception.

*/

#include "ContainerComponent.h"
#include "server/zone/objects/scene/SceneObject.h"
#include "server/zone/objects/building/BuildingObject.h"
#include "server/zone/Zone.h"
#include "server/zone/objects/creature/CreatureObject.h"
#include "server/zone/objects/player/PlayerObject.h"
#include "server/zone/objects/player/sessions/SlicingSession.h"

int ContainerComponent::canAddObject(SceneObject* sceneObject, SceneObject* object, int containmentType, String& errorDescription) {
	if (sceneObject == object) {
		errorDescription = "@container_error_message:container02"; //You cannot add something to itself.

		return TransferErrorCode::CANTADDTOITSELF;
	}

	if (object->isNoTrade() || object->containsNoTradeObjectRecursive()) {
		ManagedReference<SceneObject*> containerPlayerParent = sceneObject->getParentRecursively(SceneObjectType::PLAYERCREATURE);
		ManagedReference<SceneObject*> containerBuildingParent = sceneObject->getParentRecursively(SceneObjectType::BUILDING);
		ManagedReference<SceneObject*> containerFactoryParent = sceneObject->getParentRecursively(SceneObjectType::FACTORY);
		ManagedReference<SceneObject*> objPlayerParent = object->getParentRecursively(SceneObjectType::PLAYERCREATURE);
		ManagedReference<SceneObject*> objBuildingParent = object->getParentRecursively(SceneObjectType::BUILDING);

		if (containerFactoryParent != NULL) {
			errorDescription = "@container_error_message:container28";
			return TransferErrorCode::CANTADD;
		} else if (objPlayerParent == NULL && objBuildingParent != NULL && (containerPlayerParent != NULL || sceneObject->isPlayerCreature())) {
			ManagedReference<BuildingObject*> buio = cast<BuildingObject*>( objBuildingParent.get());

			if (buio != NULL && buio->getOwnerObjectID() != containerPlayerParent->getObjectID()) {
				errorDescription = "@container_error_message:container27";
				return TransferErrorCode::CANTREMOVE;
			}
		} else if (objPlayerParent != NULL && containerPlayerParent == NULL && containerBuildingParent != NULL && !sceneObject->isPlayerCreature()) {
			ManagedReference<BuildingObject*> buio = cast<BuildingObject*>( containerBuildingParent.get());

			if (buio != NULL && buio->getOwnerObjectID() != objPlayerParent->getObjectID()) {
				errorDescription = "@container_error_message:container28";
				return TransferErrorCode::CANTADD;
			}
		}

	}

	Locker contLocker(sceneObject->getContainerLock());

	VectorMap<String, ManagedReference<SceneObject*> >* slottedObjects = sceneObject->getSlottedObjects();
	VectorMap<uint64, ManagedReference<SceneObject*> >* containerObjects = sceneObject->getContainerObjects();

	if (containmentType >= 4) {
		Locker contLocker(sceneObject->getContainerLock());

		int arrangementGroup = containmentType - 4;

		if (object->getArrangementDescriptorSize() > arrangementGroup) {
			Vector<String> descriptors = object->getArrangementDescriptor(arrangementGroup);

			for (int i = 0; i < descriptors.size(); ++i){
				String childArrangement = descriptors.get(i);

				if (slottedObjects->contains(childArrangement)) {
					errorDescription = "@container_error_message:container04"; //This slot is already occupied.
					return TransferErrorCode::SLOTOCCUPIED;
				}
			}
		}
	} else if (containmentType == -1) {
		if (containerObjects->size() >= sceneObject->getContainerVolumeLimit()) {
			errorDescription = "@container_error_message:container03"; //This container is full.

			return TransferErrorCode::CONTAINERFULL;
		}

	} else {
		sceneObject->error("unkown containmentType in canAddObject type " + String::valueOf(containmentType));

		errorDescription = "DEBUG: cant move item unkown containmentType type";
		return TransferErrorCode::UNKNOWNCONTAIMENTTYPE;
	}

	return 0;
}

bool ContainerComponent::checkContainerPermission(SceneObject* sceneObject, CreatureObject* creature, uint16 permission) {
	ContainerPermissions* permissions = sceneObject->getContainerPermissions();

	if (permissions->getOwnerID() == creature->getObjectID()) {
		return permissions->hasOwnerPermission(permission);
	}

	PlayerObject* ghost = creature->getPlayerObject();

	if (ghost == NULL)
		return false;

	if (permission == ContainerPermissions::OPEN && ghost->isPrivileged())
		return true;

	ManagedReference<SceneObject*> parent = sceneObject->getParent().get();

	if (permission != ContainerPermissions::MOVECONTAINER && permissions->hasInheritPermissionsFromParent() && parent != NULL && parent != sceneObject) {
		return parent->checkContainerPermission(creature, permission);
	} else if (permission == ContainerPermissions::MOVECONTAINER && sceneObject->isStaticObject()) {
		return false;
	}

	SortedVector<String>* groups = ghost->getPermissionGroups();

	uint16 allowPermissions = 0, denyPermissions = 0;

	for (int i = 0; i < groups->size(); ++i) {
		String group = groups->get(i);

		uint16 allow = permissions->getAllowPermissions(group);

		allowPermissions |= allow;

		uint16 deny = permissions->getDenyPermissions(group);

		denyPermissions |= deny;
	}

	return permission & (allowPermissions & ~denyPermissions);
}

bool ContainerComponent::transferObject(SceneObject* sceneObject, SceneObject* object, int containmentType, bool notifyClient, bool allowOverflow) {
	if (sceneObject == object) {
		return false;
	}

	ManagedReference<SceneObject*> objParent = object->getParent();
	ManagedReference<Zone*> objZone = object->getLocalZone();

	if (object->containsActiveSession(SessionFacadeType::SLICING)) {
		ManagedReference<Facade*> facade = object->getActiveSession(SessionFacadeType::SLICING);
		ManagedReference<SlicingSession*> session = dynamic_cast<SlicingSession*>(facade.get());
		if (session != NULL) {
			session->cancelSession();
		}
	}

	if (objParent != NULL || objZone != NULL) {
		if (objParent != NULL)
			objParent->removeObject(object, sceneObject, notifyClient);

		if (object->getParent() != NULL) {
			object->error("error removing from from parent");

			return false;
		}

		if (objZone != NULL)
			objZone->remove(object);

		object->setZone(NULL);

		if (objParent == NULL)
			objParent = objZone;
	}

	bool update = true;

	VectorMap<String, ManagedReference<SceneObject*> >* slottedObjects = sceneObject->getSlottedObjects();
	VectorMap<uint64, ManagedReference<SceneObject*> >* containerObjects = sceneObject->getContainerObjects();

	//if (containerType == 1 || containerType == 5) {
	if (containmentType >= 4) {
		Locker contLocker(sceneObject->getContainerLock());

		int arrangementGroup = containmentType - 4;

		if (object->getArrangementDescriptorSize() > arrangementGroup) {
			Vector<String> descriptors = object->getArrangementDescriptor(arrangementGroup);

			for (int i = 0; i < descriptors.size(); ++i){
				String childArrangement = descriptors.get(i);
				if (slottedObjects->contains(childArrangement)) {
					return false;
				}
			}

			for (int i = 0; i < descriptors.size(); ++i)	{
				 slottedObjects->put(descriptors.get(i), object);
			}
		} else {
			return false;
		}

		object->setParent(sceneObject);
		object->setContainmentType(containmentType);
	} else if (containmentType == -1) { /* else if (containerType == 2 || containerType == 3) {*/
		Locker contLocker(sceneObject->getContainerLock());

		if (!allowOverflow && containerObjects->size() >= sceneObject->getContainerVolumeLimit()){
			return false;
		}

		/*if (containerObjects.contains(object->getObjectID()))
			return false*/

		if (containerObjects->put(object->getObjectID(), object) == -1)
			update = false;

		object->setParent(sceneObject);
		object->setContainmentType(containmentType);

	} else {
		sceneObject->error("unknown containment type " + String::valueOf(containmentType));
		StackTrace::printStackTrace();
		return false;
	}

	if ((containmentType >= 4) && objZone == NULL)
		sceneObject->broadcastObject(object, true);
	else if (notifyClient)
		sceneObject->broadcastMessage(object->link(sceneObject->getObjectID(), containmentType), true);

	notifyObjectInserted(sceneObject, object);

	if (update) {
		sceneObject->updateToDatabase();
		//object->updateToDatabaseWithoutChildren()();
	}

	ManagedReference<SceneObject*> rootParent = object->getRootParent();

	if (rootParent != NULL)
		rootParent->notifyObjectInsertedToChild(object, sceneObject, objParent);

	return true;
}

bool ContainerComponent::removeObject(SceneObject* sceneObject, SceneObject* object, SceneObject* destination, bool notifyClient) {
	VectorMap<String, ManagedReference<SceneObject*> >* slottedObjects = sceneObject->getSlottedObjects();
	VectorMap<uint64, ManagedReference<SceneObject*> >* containerObjects = sceneObject->getContainerObjects();

	ManagedReference<SceneObject*> objectKeeper = object;

	if (object->getParent() != sceneObject && object->getParent() != NULL) {
		ManagedReference<SceneObject*> objParent = object->getParent();

		Locker contLocker(sceneObject->getContainerLock());

		containerObjects->drop(object->getObjectID());

		if (objParent->hasObjectInContainer(object->getObjectID()) || objParent->hasObjectInSlottedContainer(object)) {
			sceneObject->error("trying to remove an object that is in a different object");
			objParent->info("i am the parent", true);

			return false;
		} else
			object->setParent(NULL);
	}

	int containedType = object->getContainmentType();

	//info("trying to remove object with containedType " + String::valueOf(containedType), true);

//	if (containedType == 4 || containedType == 5) {
	Locker contLocker(sceneObject->getContainerLock());

	int arrangementSize = object->getArrangementDescriptorSize();

	int arrangementGroup = MAX(0, containedType - 4);

	if (object->getArrangementDescriptorSize() > arrangementGroup) {
		bool removeFromSlot = false;

		Vector<String> descriptors = object->getArrangementDescriptor(arrangementGroup);

		for (int i = 0; i < descriptors.size(); ++i){
			String childArrangement = descriptors.get(i);

			ManagedReference<SceneObject*> obj = slottedObjects->get(childArrangement);

			if (slottedObjects->get(childArrangement) == object) {
				removeFromSlot = true;
				break;
			}
		}

		if (removeFromSlot) {
			for (int i = 0; i < descriptors.size(); ++i)
				slottedObjects->drop(descriptors.get(i));
		}
	}

	//	} else if (containedType == -1) {
	//Locker contLocker(sceneObject->getContainerLock());

	if (containerObjects->contains(object->getObjectID())) {
		//info("containerObjects doesnt contain specified object", true);
		//object->setParent(NULL);

		//			return false;

		containerObjects->drop(object->getObjectID());
	}

	object->setParent(NULL);

	contLocker.release();
	/*

	} else {
		sceneObject->error("unknown contained type " + String::valueOf(containedType));
		StackTrace::printStackTrace();

		return false;
	}
	*/

	if (notifyClient)
		sceneObject->broadcastMessage(object->link((uint64) 0, 0xFFFFFFFF), true);

	notifyObjectRemoved(sceneObject, object, destination);

	sceneObject->updateToDatabase();
	object->updateToDatabase();

	if (sceneObject->getParent() == NULL) {
		sceneObject->notifyObjectRemovedFromChild(object, sceneObject);
	} else {
		ManagedReference<SceneObject*> rootParent = sceneObject->getRootParent();

		if (rootParent != NULL)
			rootParent->notifyObjectRemovedFromChild(object, sceneObject);
		else
			sceneObject->notifyObjectRemovedFromChild(object, sceneObject);
	}

	return true;
}

/**
 * Is called when this object has been inserted with an object
 * @param object object that has been inserted
 */
int ContainerComponent::notifyObjectInserted(SceneObject* sceneObject, SceneObject* object) {
	return sceneObject->notifyObjectInserted(object);
}

/**
 * Is called when an object was removed
 * @param object object that has been inserted
 */
int ContainerComponent::notifyObjectRemoved(SceneObject* sceneObject, SceneObject* object, SceneObject* destination) {
	return sceneObject->notifyObjectRemoved(object);
}

<commit_msg>[Fixed] cannot 'drop' (place) Vendors in PUBLIC houses anymore...  Mantis #5994<commit_after>/*
Copyright (C) 2007 <SWGEmu>
This File is part of Core3.
This program is free software; you can redistribute
it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software
Foundation; either version 2 of the License,
or (at your option) any later version.

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

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

Linking Engine3 statically or dynamically with other modules
is making a combined work based on Engine3.
Thus, the terms and conditions of the GNU Lesser General Public License
cover the whole combination.

In addition, as a special exception, the copyright holders of Engine3
give you permission to combine Engine3 program with free software
programs or libraries that are released under the GNU LGPL and with
code included in the standard release of Core3 under the GNU LGPL
license (or modified versions of such code, with unchanged license).
You may copy and distribute such a system following the terms of the
GNU LGPL for Engine3 and the licenses of the other code concerned,
provided that you include the source code of that other code when
and as the GNU LGPL requires distribution of source code.

Note that people who make modified versions of Engine3 are not obligated
to grant this special exception for their modified versions;
it is their choice whether to do so. The GNU Lesser General Public License
gives permission to release a modified version without this exception;
this exception also makes it possible to release a modified version
which carries forward this exception.

*/

#include "ContainerComponent.h"
#include "server/zone/objects/scene/SceneObject.h"
#include "server/zone/objects/building/BuildingObject.h"
#include "server/zone/Zone.h"
#include "server/zone/objects/creature/CreatureObject.h"
#include "server/zone/objects/player/PlayerObject.h"
#include "server/zone/objects/player/sessions/SlicingSession.h"

int ContainerComponent::canAddObject(SceneObject* sceneObject, SceneObject* object, int containmentType, String& errorDescription) {
	if (sceneObject == object) {
		errorDescription = "@container_error_message:container02"; //You cannot add something to itself.

		return TransferErrorCode::CANTADDTOITSELF;
	}

	if ((object->isNoTrade() || object->containsNoTradeObjectRecursive()) && !object->isVendor()) {
		ManagedReference<SceneObject*> containerPlayerParent = sceneObject->getParentRecursively(SceneObjectType::PLAYERCREATURE);
		ManagedReference<SceneObject*> containerBuildingParent = sceneObject->getParentRecursively(SceneObjectType::BUILDING);
		ManagedReference<SceneObject*> containerFactoryParent = sceneObject->getParentRecursively(SceneObjectType::FACTORY);
		ManagedReference<SceneObject*> objPlayerParent = object->getParentRecursively(SceneObjectType::PLAYERCREATURE);
		ManagedReference<SceneObject*> objBuildingParent = object->getParentRecursively(SceneObjectType::BUILDING);

		if (containerFactoryParent != NULL) {
			errorDescription = "@container_error_message:container28";
			return TransferErrorCode::CANTADD;
		} else if (objPlayerParent == NULL && objBuildingParent != NULL && (containerPlayerParent != NULL || sceneObject->isPlayerCreature())) {
			ManagedReference<BuildingObject*> buio = cast<BuildingObject*>( objBuildingParent.get());

			if (buio != NULL && buio->getOwnerObjectID() != containerPlayerParent->getObjectID()) {

				errorDescription = "@container_error_message:container27";
				return TransferErrorCode::CANTREMOVE;
			}
		} else if (objPlayerParent != NULL && containerPlayerParent == NULL && containerBuildingParent != NULL && !sceneObject->isPlayerCreature()) {
			ManagedReference<BuildingObject*> buio = cast<BuildingObject*>( containerBuildingParent.get());

			if (buio != NULL && buio->getOwnerObjectID() != objPlayerParent->getObjectID()) {

				errorDescription = "@container_error_message:container28";
				return TransferErrorCode::CANTADD;
			}
		}

	}

	Locker contLocker(sceneObject->getContainerLock());

	VectorMap<String, ManagedReference<SceneObject*> >* slottedObjects = sceneObject->getSlottedObjects();
	VectorMap<uint64, ManagedReference<SceneObject*> >* containerObjects = sceneObject->getContainerObjects();

	if (containmentType >= 4) {
		Locker contLocker(sceneObject->getContainerLock());

		int arrangementGroup = containmentType - 4;

		if (object->getArrangementDescriptorSize() > arrangementGroup) {
			Vector<String> descriptors = object->getArrangementDescriptor(arrangementGroup);

			for (int i = 0; i < descriptors.size(); ++i){
				String childArrangement = descriptors.get(i);

				if (slottedObjects->contains(childArrangement)) {
					errorDescription = "@container_error_message:container04"; //This slot is already occupied.
					return TransferErrorCode::SLOTOCCUPIED;
				}
			}
		}
	} else if (containmentType == -1) {
		if (containerObjects->size() >= sceneObject->getContainerVolumeLimit()) {
			errorDescription = "@container_error_message:container03"; //This container is full.

			return TransferErrorCode::CONTAINERFULL;
		}

	} else {
		sceneObject->error("unknown containmentType in canAddObject type " + String::valueOf(containmentType));

		errorDescription = "DEBUG: cant move item unknown containmentType type";
		return TransferErrorCode::UNKNOWNCONTAIMENTTYPE;
	}

	return 0;
}

bool ContainerComponent::checkContainerPermission(SceneObject* sceneObject, CreatureObject* creature, uint16 permission) {
	ContainerPermissions* permissions = sceneObject->getContainerPermissions();

	if (permissions->getOwnerID() == creature->getObjectID()) {
		return permissions->hasOwnerPermission(permission);
	}

	PlayerObject* ghost = creature->getPlayerObject();

	if (ghost == NULL)
		return false;

	if (permission == ContainerPermissions::OPEN && ghost->isPrivileged())
		return true;

	ManagedReference<SceneObject*> parent = sceneObject->getParent().get();

	if (permission != ContainerPermissions::MOVECONTAINER && permissions->hasInheritPermissionsFromParent() && parent != NULL && parent != sceneObject) {
		return parent->checkContainerPermission(creature, permission);
	} else if (permission == ContainerPermissions::MOVECONTAINER && sceneObject->isStaticObject()) {
		return false;
	}

	SortedVector<String>* groups = ghost->getPermissionGroups();

	uint16 allowPermissions = 0, denyPermissions = 0;

	for (int i = 0; i < groups->size(); ++i) {
		String group = groups->get(i);

		uint16 allow = permissions->getAllowPermissions(group);

		allowPermissions |= allow;

		uint16 deny = permissions->getDenyPermissions(group);

		denyPermissions |= deny;
	}

	return permission & (allowPermissions & ~denyPermissions);
}

bool ContainerComponent::transferObject(SceneObject* sceneObject, SceneObject* object, int containmentType, bool notifyClient, bool allowOverflow) {
	if (sceneObject == object) {
		return false;
	}

	ManagedReference<SceneObject*> objParent = object->getParent();
	ManagedReference<Zone*> objZone = object->getLocalZone();

	if (object->containsActiveSession(SessionFacadeType::SLICING)) {
		ManagedReference<Facade*> facade = object->getActiveSession(SessionFacadeType::SLICING);
		ManagedReference<SlicingSession*> session = dynamic_cast<SlicingSession*>(facade.get());
		if (session != NULL) {
			session->cancelSession();
		}
	}

	if (objParent != NULL || objZone != NULL) {
		if (objParent != NULL)
			objParent->removeObject(object, sceneObject, notifyClient);

		if (object->getParent() != NULL) {
			object->error("error removing from parent");

			return false;
		}

		if (objZone != NULL)
			objZone->remove(object);

		object->setZone(NULL);

		if (objParent == NULL)
			objParent = objZone;
	}

	bool update = true;

	VectorMap<String, ManagedReference<SceneObject*> >* slottedObjects = sceneObject->getSlottedObjects();
	VectorMap<uint64, ManagedReference<SceneObject*> >* containerObjects = sceneObject->getContainerObjects();

	//if (containerType == 1 || containerType == 5) {
	if (containmentType >= 4) {
		Locker contLocker(sceneObject->getContainerLock());

		int arrangementGroup = containmentType - 4;

		if (object->getArrangementDescriptorSize() > arrangementGroup) {
			Vector<String> descriptors = object->getArrangementDescriptor(arrangementGroup);

			for (int i = 0; i < descriptors.size(); ++i){
				String childArrangement = descriptors.get(i);
				if (slottedObjects->contains(childArrangement)) {
					return false;
				}
			}

			for (int i = 0; i < descriptors.size(); ++i)	{
				 slottedObjects->put(descriptors.get(i), object);
			}
		} else {
			return false;
		}

		object->setParent(sceneObject);
		object->setContainmentType(containmentType);
	} else if (containmentType == -1) { /* else if (containerType == 2 || containerType == 3) {*/
		Locker contLocker(sceneObject->getContainerLock());

		if (!allowOverflow && containerObjects->size() >= sceneObject->getContainerVolumeLimit()){
			return false;
		}

		/*if (containerObjects.contains(object->getObjectID()))
			return false*/

		if (containerObjects->put(object->getObjectID(), object) == -1)
			update = false;

		object->setParent(sceneObject);
		object->setContainmentType(containmentType);

	} else {
		sceneObject->error("unknown containment type " + String::valueOf(containmentType));
		StackTrace::printStackTrace();
		return false;
	}

	if ((containmentType >= 4) && objZone == NULL)
		sceneObject->broadcastObject(object, true);
	else if (notifyClient)
		sceneObject->broadcastMessage(object->link(sceneObject->getObjectID(), containmentType), true);

	notifyObjectInserted(sceneObject, object);

	if (update) {
		sceneObject->updateToDatabase();
		//object->updateToDatabaseWithoutChildren()();
	}

	ManagedReference<SceneObject*> rootParent = object->getRootParent();

	if (rootParent != NULL)
		rootParent->notifyObjectInsertedToChild(object, sceneObject, objParent);

	return true;
}

bool ContainerComponent::removeObject(SceneObject* sceneObject, SceneObject* object, SceneObject* destination, bool notifyClient) {
	VectorMap<String, ManagedReference<SceneObject*> >* slottedObjects = sceneObject->getSlottedObjects();
	VectorMap<uint64, ManagedReference<SceneObject*> >* containerObjects = sceneObject->getContainerObjects();

	ManagedReference<SceneObject*> objectKeeper = object;

	if (object->getParent() != sceneObject && object->getParent() != NULL) {
		ManagedReference<SceneObject*> objParent = object->getParent();

		Locker contLocker(sceneObject->getContainerLock());

		containerObjects->drop(object->getObjectID());

		if (objParent->hasObjectInContainer(object->getObjectID()) || objParent->hasObjectInSlottedContainer(object)) {
			sceneObject->error("trying to remove an object that is in a different object");
			objParent->info("i am the parent", true);

			return false;
		} else
			object->setParent(NULL);
	}

	int containedType = object->getContainmentType();

	//info("trying to remove object with containedType " + String::valueOf(containedType), true);

//	if (containedType == 4 || containedType == 5) {
	Locker contLocker(sceneObject->getContainerLock());

	int arrangementSize = object->getArrangementDescriptorSize();

	int arrangementGroup = MAX(0, containedType - 4);

	if (object->getArrangementDescriptorSize() > arrangementGroup) {
		bool removeFromSlot = false;

		Vector<String> descriptors = object->getArrangementDescriptor(arrangementGroup);

		for (int i = 0; i < descriptors.size(); ++i){
			String childArrangement = descriptors.get(i);

			ManagedReference<SceneObject*> obj = slottedObjects->get(childArrangement);

			if (slottedObjects->get(childArrangement) == object) {
				removeFromSlot = true;
				break;
			}
		}

		if (removeFromSlot) {
			for (int i = 0; i < descriptors.size(); ++i)
				slottedObjects->drop(descriptors.get(i));
		}
	}

	//	} else if (containedType == -1) {
	//Locker contLocker(sceneObject->getContainerLock());

	if (containerObjects->contains(object->getObjectID())) {
		//info("containerObjects doesnt contain specified object", true);
		//object->setParent(NULL);

		//			return false;

		containerObjects->drop(object->getObjectID());
	}

	object->setParent(NULL);

	contLocker.release();
	/*

	} else {
		sceneObject->error("unknown contained type " + String::valueOf(containedType));
		StackTrace::printStackTrace();

		return false;
	}
	*/

	if (notifyClient)
		sceneObject->broadcastMessage(object->link((uint64) 0, 0xFFFFFFFF), true);

	notifyObjectRemoved(sceneObject, object, destination);

	sceneObject->updateToDatabase();
	object->updateToDatabase();

	if (sceneObject->getParent() == NULL) {
		sceneObject->notifyObjectRemovedFromChild(object, sceneObject);
	} else {
		ManagedReference<SceneObject*> rootParent = sceneObject->getRootParent();

		if (rootParent != NULL)
			rootParent->notifyObjectRemovedFromChild(object, sceneObject);
		else
			sceneObject->notifyObjectRemovedFromChild(object, sceneObject);
	}

	return true;
}

/**
 * Is called when this object has been inserted with an object
 * @param object object that has been inserted
 */
int ContainerComponent::notifyObjectInserted(SceneObject* sceneObject, SceneObject* object) {
	return sceneObject->notifyObjectInserted(object);
}

/**
 * Is called when an object was removed
 * @param object object that has been inserted
 */
int ContainerComponent::notifyObjectRemoved(SceneObject* sceneObject, SceneObject* object, SceneObject* destination) {
	return sceneObject->notifyObjectRemoved(object);
}

<|endoftext|>


<commit_before>// -*- mode: c++; coding: utf-8 -*-
/*! @file program.cpp
    @brief Implementation of Program class
*/
#include "program.hpp"
#include "pathtype.hpp"
#include "genotype.hpp"
#include "gridsearch.hpp"
#include "gradient_descent.hpp"

#include <wtl/exception.hpp>
#include <wtl/debug.hpp>
#include <wtl/iostr.hpp>
#include <wtl/getopt.hpp>
#include <wtl/zfstream.hpp>

#include <boost/filesystem.hpp>

#include <regex>

namespace likeligrid {

namespace fs = boost::filesystem;
namespace po = boost::program_options;

inline po::options_description general_desc() {HERE;
    po::options_description description("General");
    description.add_options()
        ("help,h", po::value<bool>()->default_value(false)->implicit_value(true), "print this help")
        ("verbose,v", po::value<bool>()->default_value(false)->implicit_value(true), "verbose output")
        ("test", po::value<int>()->default_value(0)->implicit_value(1));
    return description;
}

po::options_description Program::options_desc() {HERE;
    po::options_description description("Program");
    description.add_options()
        ("parallel,j", po::value(&CONCURRENCY)->default_value(CONCURRENCY))
        ("max-sites,s", po::value(&MAX_SITES)->default_value(MAX_SITES))
        ("gradient,g", po::value(&GRADIENT_MODE)->default_value(GRADIENT_MODE)->implicit_value(true))
        ("epistasis,e", po::value(&EPISTASIS_PAIR)->default_value(EPISTASIS_PAIR)->multitoken());
    return description;
}

po::options_description Program::positional_desc() {HERE;
    po::options_description description("Positional");
    description.add_options()
        ("infile", po::value(&INFILE)->default_value(INFILE));
    return description;
}

void Program::help_and_exit() {HERE;
    auto description = general_desc();
    description.add(options_desc());
    // do not print positional arguments as options
    std::cout << "Usage: likeligrid [options] infile\n" << std::endl;
    description.print(std::cout);
    throw wtl::ExitSuccess();
}

//! Unit test for each class
void Program::test(const int flag) {HERE;
    switch (flag) {
      case 0:
        break;
      case 1:
        GridSearch::test();
        GradientDescent::test();
        throw wtl::ExitSuccess();
      case 2:
        GenotypeModel::test();
        PathtypeModel::test();
        throw wtl::ExitSuccess();
      case 3: {
        wtl::izfstream ist(INFILE);
        GenotypeModel model(ist, MAX_SITES);
        model.benchmark(CONCURRENCY);
        throw wtl::ExitSuccess();
      }
      default:
        throw std::runtime_error("Unknown argument for --test");
    }
}

Program::Program(const std::vector<std::string>& arguments) {HERE;
    std::cout << wtl::join(arguments, " ") << std::endl;
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.precision(15);
    std::cerr.precision(6);
    wtl::set_SIGINT_handler();

    auto description = general_desc();
    description.add(options_desc());
    description.add(positional_desc());
    po::positional_options_description positional;
    positional.add("infile", 1);
    po::variables_map vm;
    po::store(po::command_line_parser({arguments.begin() + 1, arguments.end()}).
              options(description).
              positional(positional).run(), vm);
    if (vm["help"].as<bool>()) {help_and_exit();}
    po::notify(vm);
    if (EPISTASIS_PAIR.size() != 2U) {
        throw std::runtime_error("EPISTASIS_PAIR.size() != 2U");
    }

    if (vm["verbose"].as<bool>()) {
        std::cerr << wtl::iso8601datetime() << std::endl;
        std::cerr << wtl::flags_into_string(vm) << std::endl;
    }
    test(vm["test"].as<int>());
}

void Program::run() {HERE;
    std::pair<size_t, size_t> epistasis{EPISTASIS_PAIR[0], EPISTASIS_PAIR[1]};
    try {
        if (GRADIENT_MODE) {
            GradientDescent gradient_descent(INFILE, MAX_SITES, epistasis, CONCURRENCY);
            fs::current_path(fs::path(INFILE).parent_path());
            wtl::ozfstream ost(gradient_descent.outfile());
            ost.precision(std::cout.precision());
            std::cerr << "outfile: " << ost.path() << std::endl;
            gradient_descent.run(ost);
        } else if (INFILE == "-") {
            GridSearch searcher(std::cin, MAX_SITES, epistasis, CONCURRENCY);
            searcher.run(false);
        } else {
            GridSearch searcher(INFILE, MAX_SITES, epistasis, CONCURRENCY);
            // after constructor success
            const std::string outdir = make_outdir();
            fs::current_path(outdir);
            searcher.run(true);
        }
    } catch (const wtl::KeyboardInterrupt& e) {
        std::cerr << e.what() << std::endl;
    } catch (const lnpnan_error& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }
}

std::string Program::make_outdir() const {
    std::smatch mobj;
    std::regex_search(INFILE, mobj, std::regex("([^/]+?)\\.[^/]+$"));
    std::ostringstream oss;
    oss << mobj.str(1) << "-s" << MAX_SITES;
    if (EPISTASIS_PAIR[0] != EPISTASIS_PAIR[1]) {
        oss << "-e" << EPISTASIS_PAIR[0]
            <<  "x" << EPISTASIS_PAIR[1];
    }
    const std::string outdir = oss.str();
    fs::create_directory(outdir);
    return outdir;
}

} // namespace likeligrid
<commit_msg>Use po::bool_switch()<commit_after>// -*- mode: c++; coding: utf-8 -*-
/*! @file program.cpp
    @brief Implementation of Program class
*/
#include "program.hpp"
#include "pathtype.hpp"
#include "genotype.hpp"
#include "gridsearch.hpp"
#include "gradient_descent.hpp"

#include <wtl/exception.hpp>
#include <wtl/debug.hpp>
#include <wtl/iostr.hpp>
#include <wtl/getopt.hpp>
#include <wtl/zfstream.hpp>

#include <boost/filesystem.hpp>

#include <regex>

namespace likeligrid {

namespace fs = boost::filesystem;
namespace po = boost::program_options;

inline po::options_description general_desc() {HERE;
    po::options_description description("General");
    description.add_options()
        ("help,h", po::bool_switch(), "print this help")
        ("verbose,v", po::bool_switch(), "verbose output")
        ("test", po::value<int>()->default_value(0)->implicit_value(1));
    return description;
}

po::options_description Program::options_desc() {HERE;
    po::options_description description("Program");
    description.add_options()
        ("parallel,j", po::value(&CONCURRENCY)->default_value(CONCURRENCY))
        ("max-sites,s", po::value(&MAX_SITES)->default_value(MAX_SITES))
        ("gradient,g", po::bool_switch(&GRADIENT_MODE))
        ("epistasis,e", po::value(&EPISTASIS_PAIR)->default_value(EPISTASIS_PAIR)->multitoken());
    return description;
}

po::options_description Program::positional_desc() {HERE;
    po::options_description description("Positional");
    description.add_options()
        ("infile", po::value(&INFILE)->default_value(INFILE));
    return description;
}

void Program::help_and_exit() {HERE;
    auto description = general_desc();
    description.add(options_desc());
    // do not print positional arguments as options
    std::cout << "Usage: likeligrid [options] infile\n" << std::endl;
    description.print(std::cout);
    throw wtl::ExitSuccess();
}

//! Unit test for each class
void Program::test(const int flag) {HERE;
    switch (flag) {
      case 0:
        break;
      case 1:
        GridSearch::test();
        GradientDescent::test();
        throw wtl::ExitSuccess();
      case 2:
        GenotypeModel::test();
        PathtypeModel::test();
        throw wtl::ExitSuccess();
      case 3: {
        wtl::izfstream ist(INFILE);
        GenotypeModel model(ist, MAX_SITES);
        model.benchmark(CONCURRENCY);
        throw wtl::ExitSuccess();
      }
      default:
        throw std::runtime_error("Unknown argument for --test");
    }
}

Program::Program(const std::vector<std::string>& arguments) {HERE;
    std::cout << wtl::join(arguments, " ") << std::endl;
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.precision(15);
    std::cerr.precision(6);
    wtl::set_SIGINT_handler();

    auto description = general_desc();
    description.add(options_desc());
    description.add(positional_desc());
    po::positional_options_description positional;
    positional.add("infile", 1);
    po::variables_map vm;
    po::store(po::command_line_parser({arguments.begin() + 1, arguments.end()}).
              options(description).
              positional(positional).run(), vm);
    if (vm["help"].as<bool>()) {help_and_exit();}
    po::notify(vm);
    if (EPISTASIS_PAIR.size() != 2U) {
        throw std::runtime_error("EPISTASIS_PAIR.size() != 2U");
    }

    if (vm["verbose"].as<bool>()) {
        std::cerr << wtl::iso8601datetime() << std::endl;
        std::cerr << wtl::flags_into_string(vm) << std::endl;
    }
    test(vm["test"].as<int>());
}

void Program::run() {HERE;
    std::pair<size_t, size_t> epistasis{EPISTASIS_PAIR[0], EPISTASIS_PAIR[1]};
    try {
        if (GRADIENT_MODE) {
            GradientDescent gradient_descent(INFILE, MAX_SITES, epistasis, CONCURRENCY);
            fs::current_path(fs::path(INFILE).parent_path());
            wtl::ozfstream ost(gradient_descent.outfile());
            ost.precision(std::cout.precision());
            std::cerr << "outfile: " << ost.path() << std::endl;
            gradient_descent.run(ost);
        } else if (INFILE == "-") {
            GridSearch searcher(std::cin, MAX_SITES, epistasis, CONCURRENCY);
            searcher.run(false);
        } else {
            GridSearch searcher(INFILE, MAX_SITES, epistasis, CONCURRENCY);
            // after constructor success
            const std::string outdir = make_outdir();
            fs::current_path(outdir);
            searcher.run(true);
        }
    } catch (const wtl::KeyboardInterrupt& e) {
        std::cerr << e.what() << std::endl;
    } catch (const lnpnan_error& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }
}

std::string Program::make_outdir() const {
    std::smatch mobj;
    std::regex_search(INFILE, mobj, std::regex("([^/]+?)\\.[^/]+$"));
    std::ostringstream oss;
    oss << mobj.str(1) << "-s" << MAX_SITES;
    if (EPISTASIS_PAIR[0] != EPISTASIS_PAIR[1]) {
        oss << "-e" << EPISTASIS_PAIR[0]
            <<  "x" << EPISTASIS_PAIR[1];
    }
    const std::string outdir = oss.str();
    fs::create_directory(outdir);
    return outdir;
}

} // namespace likeligrid
<|endoftext|>


<commit_before>#include "error_checked.hpp"

#include <string>

constexpr static bool output_calls = false;

#define BARK do { if(output_calls) std::cerr << __FUNCTION__ << std::endl; } while(false)

namespace rusql { namespace mysql {
	ErrorCheckerConnection::ErrorCheckerConnection(MYSQL* connection_, const char* f)
	: connection(connection_)
	, function(f) {
		check_and_throw(std::string("Before ") + function);
	}

	void ErrorCheckerConnection::check_and_throw(std::string const f) {
		if(mysql_errno(connection)){
			char const * const error = mysql_error(connection);
			if(error){
				throw SQLError(f, error);
			}
		}
	}

	ErrorCheckerConnection::~ErrorCheckerConnection() {
		check_and_throw(function);
	}

	ErrorCheckerStatement::ErrorCheckerStatement(MYSQL_STMT* statement_, char const* f)
	: statement(statement_)
	, function(f)
	{
		check_and_throw(std::string("Before ") + function);
	}

	ErrorCheckerStatement::~ErrorCheckerStatement() {
		check_and_throw(function);
	}

	void ErrorCheckerStatement::check_and_throw(std::string const f) {
		auto const error_code = mysql_stmt_errno(statement);
		char const * const error = mysql_stmt_error(statement);
		if(error_code != 0 || error[0]){
			throw SQLError(f, error);
		}
	}

	#define CHECK ErrorCheckerConnection(connection, __FUNCTION__)
	MYSQL* init(MYSQL* connection){
		BARK;
		CHECK;
		return mysql_init(connection);
	}

	void close(MYSQL* connection) {
		BARK;
		CHECK;
		return mysql_close(connection);
	}

	int ping(MYSQL* connection){
		BARK;
		CHECK;
		return mysql_ping(connection);
	}

	MYSQL_RES* use_result(MYSQL* connection) {
		BARK;
		CHECK;
		return mysql_use_result(connection);
	}

	size_t field_count(MYSQL* connection){
		BARK;
		CHECK;
		return mysql_field_count(connection);
	}

	MYSQL_STMT* stmt_init(MYSQL* connection){
		BARK;
		CHECK;
		return mysql_stmt_init(connection);
	}

	MYSQL* connect(
		MYSQL* connection,
		boost::optional<std::string const> host,
		boost::optional<std::string const> user,
		boost::optional<std::string const> password,
		boost::optional<std::string const> database,
		unsigned long const port,
		boost::optional<std::string const> unix_socket,
		unsigned long client_flags
	) {
		BARK;
		CHECK;
		auto char_ptr = [](boost::optional<std::string const> x) { return (x ? x->c_str() : nullptr); };
		return mysql_real_connect(connection, char_ptr(host), char_ptr(user), char_ptr(password), char_ptr(database), port, char_ptr(unix_socket), client_flags);
	}

	int query(MYSQL* connection, std::string const query){
		BARK;
		CHECK;
		return mysql_real_query(connection, query.c_str(), query.length());
	}

	MYSQL_FIELD* fetch_field(MYSQL_RES* result) {
		BARK;
		return mysql_fetch_field(result);
	}

	MYSQL_FIELD_OFFSET field_seek(MYSQL_RES* result, MYSQL_FIELD_OFFSET offset){
		BARK;
		return mysql_field_seek(result, offset);
	}

	unsigned long* fetch_lengths(MYSQL_RES* result){
		BARK;
		auto const r = mysql_fetch_lengths(result);
		if(r == nullptr){
			throw SQLError(__FUNCTION__, "Failed to fetch field lengths (probably no current row: forgot to call fetch_row or no more rows)");
		}

		return r;
	}

	unsigned int num_fields(MYSQL_RES* result) {
		BARK;
		return mysql_num_fields(result);
	}

	void free_result(MYSQL_RES* result){
		BARK;
		mysql_free_result(result);
	}

	MYSQL_ROW fetch_row(MYSQL* connection, MYSQL_RES* result){
		BARK;
		CHECK;
		return mysql_fetch_row(result);
	}

	unsigned long long num_rows(MYSQL *connection, MYSQL_RES *result) {
		BARK;
		CHECK;
		return mysql_num_rows(result);
	}

	unsigned long long insert_id(MYSQL *connection) {
		BARK;
		return mysql_insert_id(connection);
	}

	unsigned long stmt_param_count(MYSQL_STMT* statement){
		BARK;
		return mysql_stmt_param_count(statement);
	}

	unsigned long stmt_field_count(MYSQL_STMT* statement){
		BARK;
		return mysql_stmt_field_count(statement);
	}

	#undef CHECK

	#define CHECK ErrorCheckerStatement(statement, __FUNCTION__)
	my_bool stmt_bind_param(MYSQL_STMT* statement, MYSQL_BIND* binds){
		BARK;
		CHECK;
		return mysql_stmt_bind_param(statement, binds);
	}

	my_bool stmt_bind_result(MYSQL_STMT* statement, MYSQL_BIND* binds){
		BARK;
		CHECK;
		return mysql_stmt_bind_result(statement, binds);
	}

	int stmt_fetch_column(MYSQL_STMT* statement, MYSQL_BIND* bind, unsigned int column, unsigned long offset) {
		BARK;
		CHECK;
		return mysql_stmt_fetch_column(statement, bind, column, offset);
	}

	my_bool stmt_close(MYSQL_STMT* statement){
		BARK;
		CHECK;
		return mysql_stmt_close(statement);
	}

	int stmt_prepare(MYSQL_STMT* statement, std::string q){
		BARK;
		CHECK;
		return mysql_stmt_prepare(statement, q.c_str(), q.length());
	}

	unsigned long long stmt_insert_id(MYSQL_STMT* statement) {
		BARK;
		return mysql_stmt_insert_id(statement);
	}

	void stmt_store_result(MYSQL_STMT *statement) {
		BARK;
		CHECK;
		if(mysql_stmt_store_result(statement) != 0) {
			throw SQLError(std::string(__FUNCTION__) + " failed, but mysql didn't notice");
		}
	}

	unsigned long long stmt_num_rows(MYSQL_STMT *statement) {
		BARK;
		return mysql_stmt_num_rows(statement);
	}

	int stmt_execute(MYSQL_STMT* statement){
		BARK;
		int result;
		{
			CHECK;
			result = mysql_stmt_execute(statement);
		}

		if(result != 0){
			throw SQLError(std::string(__FUNCTION__) + " failed, but mysql didn't notice (function returned error, but errno and errmsg unset)");
		}
		return result;
	}

	int stmt_fetch(MYSQL_STMT* statement){
		BARK;
		int result;

		{
			CHECK;
			result = mysql_stmt_fetch(statement);
		}

		if(!(result == 0 || result == MYSQL_NO_DATA || result == MYSQL_DATA_TRUNCATED)){
			throw SQLError(std::string(__FUNCTION__) + "failed, but mysql didn't notice (function returned error, but errno and errmsg unset)");
		}

		return result;
	}
	#undef CHECK
}}
<commit_msg>Add required header in release mode, for BARK<commit_after>#include "error_checked.hpp"

#include <string>
#include <iostream>

constexpr static bool output_calls = false;

#define BARK do { if(output_calls) std::cerr << __FUNCTION__ << std::endl; } while(false)

namespace rusql { namespace mysql {
	ErrorCheckerConnection::ErrorCheckerConnection(MYSQL* connection_, const char* f)
	: connection(connection_)
	, function(f) {
		check_and_throw(std::string("Before ") + function);
	}

	void ErrorCheckerConnection::check_and_throw(std::string const f) {
		if(mysql_errno(connection)){
			char const * const error = mysql_error(connection);
			if(error){
				throw SQLError(f, error);
			}
		}
	}

	ErrorCheckerConnection::~ErrorCheckerConnection() {
		check_and_throw(function);
	}

	ErrorCheckerStatement::ErrorCheckerStatement(MYSQL_STMT* statement_, char const* f)
	: statement(statement_)
	, function(f)
	{
		check_and_throw(std::string("Before ") + function);
	}

	ErrorCheckerStatement::~ErrorCheckerStatement() {
		check_and_throw(function);
	}

	void ErrorCheckerStatement::check_and_throw(std::string const f) {
		auto const error_code = mysql_stmt_errno(statement);
		char const * const error = mysql_stmt_error(statement);
		if(error_code != 0 || error[0]){
			throw SQLError(f, error);
		}
	}

	#define CHECK ErrorCheckerConnection(connection, __FUNCTION__)
	MYSQL* init(MYSQL* connection){
		BARK;
		CHECK;
		return mysql_init(connection);
	}

	void close(MYSQL* connection) {
		BARK;
		CHECK;
		return mysql_close(connection);
	}

	int ping(MYSQL* connection){
		BARK;
		CHECK;
		return mysql_ping(connection);
	}

	MYSQL_RES* use_result(MYSQL* connection) {
		BARK;
		CHECK;
		return mysql_use_result(connection);
	}

	size_t field_count(MYSQL* connection){
		BARK;
		CHECK;
		return mysql_field_count(connection);
	}

	MYSQL_STMT* stmt_init(MYSQL* connection){
		BARK;
		CHECK;
		return mysql_stmt_init(connection);
	}

	MYSQL* connect(
		MYSQL* connection,
		boost::optional<std::string const> host,
		boost::optional<std::string const> user,
		boost::optional<std::string const> password,
		boost::optional<std::string const> database,
		unsigned long const port,
		boost::optional<std::string const> unix_socket,
		unsigned long client_flags
	) {
		BARK;
		CHECK;
		auto char_ptr = [](boost::optional<std::string const> x) { return (x ? x->c_str() : nullptr); };
		return mysql_real_connect(connection, char_ptr(host), char_ptr(user), char_ptr(password), char_ptr(database), port, char_ptr(unix_socket), client_flags);
	}

	int query(MYSQL* connection, std::string const query){
		BARK;
		CHECK;
		return mysql_real_query(connection, query.c_str(), query.length());
	}

	MYSQL_FIELD* fetch_field(MYSQL_RES* result) {
		BARK;
		return mysql_fetch_field(result);
	}

	MYSQL_FIELD_OFFSET field_seek(MYSQL_RES* result, MYSQL_FIELD_OFFSET offset){
		BARK;
		return mysql_field_seek(result, offset);
	}

	unsigned long* fetch_lengths(MYSQL_RES* result){
		BARK;
		auto const r = mysql_fetch_lengths(result);
		if(r == nullptr){
			throw SQLError(__FUNCTION__, "Failed to fetch field lengths (probably no current row: forgot to call fetch_row or no more rows)");
		}

		return r;
	}

	unsigned int num_fields(MYSQL_RES* result) {
		BARK;
		return mysql_num_fields(result);
	}

	void free_result(MYSQL_RES* result){
		BARK;
		mysql_free_result(result);
	}

	MYSQL_ROW fetch_row(MYSQL* connection, MYSQL_RES* result){
		BARK;
		CHECK;
		return mysql_fetch_row(result);
	}

	unsigned long long num_rows(MYSQL *connection, MYSQL_RES *result) {
		BARK;
		CHECK;
		return mysql_num_rows(result);
	}

	unsigned long long insert_id(MYSQL *connection) {
		BARK;
		return mysql_insert_id(connection);
	}

	unsigned long stmt_param_count(MYSQL_STMT* statement){
		BARK;
		return mysql_stmt_param_count(statement);
	}

	unsigned long stmt_field_count(MYSQL_STMT* statement){
		BARK;
		return mysql_stmt_field_count(statement);
	}

	#undef CHECK

	#define CHECK ErrorCheckerStatement(statement, __FUNCTION__)
	my_bool stmt_bind_param(MYSQL_STMT* statement, MYSQL_BIND* binds){
		BARK;
		CHECK;
		return mysql_stmt_bind_param(statement, binds);
	}

	my_bool stmt_bind_result(MYSQL_STMT* statement, MYSQL_BIND* binds){
		BARK;
		CHECK;
		return mysql_stmt_bind_result(statement, binds);
	}

	int stmt_fetch_column(MYSQL_STMT* statement, MYSQL_BIND* bind, unsigned int column, unsigned long offset) {
		BARK;
		CHECK;
		return mysql_stmt_fetch_column(statement, bind, column, offset);
	}

	my_bool stmt_close(MYSQL_STMT* statement){
		BARK;
		CHECK;
		return mysql_stmt_close(statement);
	}

	int stmt_prepare(MYSQL_STMT* statement, std::string q){
		BARK;
		CHECK;
		return mysql_stmt_prepare(statement, q.c_str(), q.length());
	}

	unsigned long long stmt_insert_id(MYSQL_STMT* statement) {
		BARK;
		return mysql_stmt_insert_id(statement);
	}

	void stmt_store_result(MYSQL_STMT *statement) {
		BARK;
		CHECK;
		if(mysql_stmt_store_result(statement) != 0) {
			throw SQLError(std::string(__FUNCTION__) + " failed, but mysql didn't notice");
		}
	}

	unsigned long long stmt_num_rows(MYSQL_STMT *statement) {
		BARK;
		return mysql_stmt_num_rows(statement);
	}

	int stmt_execute(MYSQL_STMT* statement){
		BARK;
		int result;
		{
			CHECK;
			result = mysql_stmt_execute(statement);
		}

		if(result != 0){
			throw SQLError(std::string(__FUNCTION__) + " failed, but mysql didn't notice (function returned error, but errno and errmsg unset)");
		}
		return result;
	}

	int stmt_fetch(MYSQL_STMT* statement){
		BARK;
		int result;

		{
			CHECK;
			result = mysql_stmt_fetch(statement);
		}

		if(!(result == 0 || result == MYSQL_NO_DATA || result == MYSQL_DATA_TRUNCATED)){
			throw SQLError(std::string(__FUNCTION__) + "failed, but mysql didn't notice (function returned error, but errno and errmsg unset)");
		}

		return result;
	}
	#undef CHECK
}}
<|endoftext|>


<commit_before>//
// Created by Miguel Rentes on 30/01/2017.
//

#include "STL.h"

void printKMax(int arr[], int n, int k) {
    deque<int> mydeque;
    int greatest = 0;
    int value = 0;
    int index = 0;
    int iteration = 0;
    // pushing all values to the deque
    for (int i = n-1; i >= 0; i--) {
        mydeque.push_front(arr[i]);
    }
    // pushing all the greatest values
    // on each k-elements
    // to the back of the deque
    for (int i = 0; i < n; ) {
        if (index < k) {
            value = mydeque[i];
            if (value > greatest)
                greatest = value;
            if (index == k - 1) {
                cout << greatest << " ";
                greatest = 0;
                index = 0;
                iteration++;
                i = iteration;
            } else {
                index++;
                i++;
            }
        }
    }
    cout << endl;
}

int main(void) {
    int t;
    cin >> t;
    while (t > 0) {
        int n, k;
        cin >> n >> k;
        int i;
        int arr[n];
        for (i = 0; i < n; i++)
            cin >> arr[i];
        printKMax(arr, n, k);
        t--;
    }
    return EXIT_SUCCESS;
}<commit_msg>Starts solution for the Deque-STL challenge.<commit_after>//
// Created by Miguel Rentes on 30/01/2017.
//

#include "STL.h"

void printKMax(int arr[], int n, int k) {
    deque<int> mydeque;
    int greatest = 0;
    int value = 0;
    int index = 0;
    std::deque<int>::iterator it;
    for (int i = 0; i < n; i++) {
        mydeque.push_front(arr[i]);
    }
    for (int i = 0; i <= n-k; i++) {
        it = mydeque.begin();
        while (index < k) {
            value = *it;
            if (value > greatest)
                greatest = value;
            it++;
            index++;
        }
        mydeque.pop_front();
        mydeque.push_back(greatest);
        greatest = 0;
        index = 0;
    }
    for (int i = 0; i <= n-k; i++) {
        cout << mydeque.back() << " ";
        mydeque.pop_back();
    }
    cout << endl;
}

int main(void) {
    int t;
    cin >> t;
    while (t > 0) {
        int n, k;
        cin >> n >> k;
        int i;
        int arr[n];
        for (i = 0; i < n; i++)
            cin >> arr[i];
        printKMax(arr, n, k);
        t--;
    }
    return EXIT_SUCCESS;
}<|endoftext|>


<commit_before>//
// Created by Miguel Rentes on 30/01/2017.
//

#include "STL.h"

void printKMax(int arr[], int n, int k) {
    deque<int> mydeque;
    int greatest = 0;
    int pop = 0;
    // creating the deque from the array k-elements
//    for (int i = 0; i < n-k+1; i++) {
//        for (int j = i; j < i+k; j++) {
//            mydeque.push_back(arr[j]);
//        }
//        // after each evaluation we pop the front value
//        for (int j = 0; j < k; j++) {
//            int value_front;
//            value_front = mydeque.front();
//            mydeque.pop_front();
//            if (value_front > greatest)
//                greatest = value_front;
//        }
//        cout << greatest << " ";
//        greatest = 0;
//    }
    for (int i = 0; i < n;) {
        mydeque.push_back(arr[i]);
        int value_back = mydeque.back();
        if (value_back > greatest)
            greatest = value_back;
        mydeque.pop_back();
        pop++;
        if (pop % k == 0) {
            cout << greatest << " ";
            greatest = 0;
            i=i-k+2;
            pop = 0;
        }
        else i++;
    }
    cout << endl;
}

int main(void) {
    int t;
    cin >> t;
    while (t > 0) {
        int n, k;
        cin >> n >> k;
        int i;
        int arr[n];
        for (i = 0; i < n; i++)
            cin >> arr[i];
        printKMax(arr, n, k);
        t--;
    }
    return EXIT_SUCCESS;
}<commit_msg>Starts solution for Deque-STL challenge.<commit_after>//
// Created by Miguel Rentes on 30/01/2017.
//

#include "STL.h"

void printKMax(int arr[], int n, int k) {
    deque<int> mydeque;
    int greatest = 0;
    int pop = 0;

    for (int i = 0; i < n;) {
        mydeque.push_back(arr[i]);
        int value_back = mydeque.back();
        if (value_back > greatest)
            greatest = value_back;
        mydeque.pop_back();
        pop++;
        if (pop % k == 0) {
            cout << greatest << " ";
            greatest = 0;
            i=i-k+2;
            pop = 0;
        }
        else i++;
    }
    cout << endl;
}

int main(void) {
    int t;
    cin >> t;
    while (t > 0) {
        int n, k;
        cin >> n >> k;
        int i;
        int arr[n];
        for (i = 0; i < n; i++)
            cin >> arr[i];
        printKMax(arr, n, k);
        t--;
    }
    return EXIT_SUCCESS;
}<|endoftext|>


<commit_before>/*
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 */

#include "../dbmanager.h"
#include "../iconmanager.h"
#include "../wizards/newdbwizard.h"

#include "dbdialog.h"

DbDialog::DbDialog(QWidget *parent)
  : QDialog(parent)
{
  setupUi(this);
  setupWidgets();
  setupConnections();

  db = NULL;
  reload();
}

void DbDialog::accept()
{
  if(db->isOpen()) {
    close();
    return;
  }

  apply();

  QDialog::accept();
  close();
}

void DbDialog::apply() {
  if(db->isOpen()) {
    return;
  }

  db->setHostName(hostEdit->text());
  db->setUserName(userEdit->text());
  db->setPassword(passEdit->text());
  db->setDatabaseName(dbEdit->text());

  DbManager::update(db);
}

/**
 * Forwards the signal from NewDbWizard to MainWindow.
 */
void DbDialog::forwardAccept()
{
}

void DbDialog::refresh(QModelIndex index)
{
  if(dbListView->selectionModel()->selectedRows().contains(index))
    reload();
}

/**
 * Re-fills all fields and enables/disables widgets
 */
void DbDialog::reload()
{
  bool emptyList = DbManager::getDbList().size() == 0;
  bool selected = !emptyList
                  && dbListView->selectionModel()->selection().size() > 0;
  bool open = selected && db->isOpen();

  groupBox->setEnabled(selected && !open);
  toggleButton->setEnabled(selected);
  remButton->setEnabled(selected);

  if(open)
  {
    toggleButton->setIcon(IconManager::get("connect_no"));
    toggleButton->setText(tr("Disconnect"));
  }
  else
  {
    toggleButton->setIcon(IconManager::get("connect_creating"));
    toggleButton->setText(tr("Connect"));
  }

  if(DbManager::getDbList().size() > 0 && db)
  {
    hostEdit->setText(db->hostName());
    userEdit->setText(db->userName());
    saveCheckBox->setChecked(!open && !db->password().isEmpty());
    passEdit->setText(db->password());
    dbTypeComboBox->setCurrentDriver(db->driverName());
    dbEdit->setText(db->databaseName());
  }

  dbBrowseButton->setVisible(false);
  resultLabel->setText(tr("<- Click to test"));
}

void DbDialog::removeCurrent()
{
  int index = dbListView->currentIndex().row();
  if(DbManager::getDatabase(index)->isOpen())
  {
    QMessageBox::critical(this,
                          tr("Cannot remove"),
                          tr("You must close the database before remove it.")
                          );
    return;
  }
  DbManager::removeDatabase(index);
  reload();
}

/**
 * Must be called to enter the Edit mode
 */
void DbDialog::setDatabase(QModelIndex index)
{
  QItemSelectionModel *m = dbListView->selectionModel();
  m->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
  db = DbManager::getDatabase(index.row());

  reload();
}

void DbDialog::setupConnections()
{
  // buttons
  connect(addButton,    SIGNAL(clicked()), addWzd,  SLOT(exec()));
  connect(remButton,    SIGNAL(clicked()), this,    SLOT(removeCurrent()));
  connect(testButton,   SIGNAL(clicked()), this,    SLOT(testConnection()));
  connect(toggleButton, SIGNAL(clicked()), this,    SLOT(toggleConnection()));
  connect(buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()),
          this, SLOT(apply()));
  connect(buttonBox->button(QDialogButtonBox::Reset), SIGNAL(clicked()),
          this, SLOT(reload()));

  // list view
  connect(dbListView, SIGNAL(clicked(QModelIndex)),
          this, SLOT(setDatabase(QModelIndex)));

  connect(addWzd, SIGNAL(accepted()), this, SLOT(forwardAccept()));

  connect(DbManager::instance(), SIGNAL(statusChanged(QModelIndex)),
          this, SLOT(refresh(QModelIndex)));
}

void DbDialog::setupWidgets()
{
  addWzd = new NewDbWizard(this);
  dbBrowseButton->setVisible(false);
  dbListView->setModel(DbManager::model());

  QCompleter *c = new QCompleter(QStringList("localhost"), this);
  c->setCompletionMode(QCompleter::InlineCompletion);
  hostEdit->setCompleter(c);

  // loading icons from theme
  addButton->setIcon(IconManager::get("list-add"));
  remButton->setIcon(IconManager::get("list-remove"));
//  hostLabel->setPixmap(IconManager::get("network-server")
//                       .pixmap(QSize(32, 32)));
//  userLabel->setPixmap(IconManager::get("user-info")
//                         .pixmap(QSize(32, 32)));
//  pswdLabel->setPixmap(IconManager::get("dialog-password")
//                         .pixmap(QSize(32, 32)));
  toggleButton->setIcon(IconManager::get("connect_creating"));
}

void DbDialog::testConnection()
{
  QSqlDatabase db = QSqlDatabase::addDatabase(
      dbTypeComboBox->currentDriverName(), "testdb");
  db.setHostName(hostEdit->text());
  db.setUserName(userEdit->text());
  db.setPassword(passEdit->text());
  db.setDatabaseName(dbEdit->text());

  if(db.lastError().type() == QSqlError::NoError)
  {
    resultLabel->setText(tr("Connection succeded"));
  }
  else
  {
    resultLabel->setText(tr("Connection failed"));
    QMessageBox::critical(this,
                          tr("Connection failed"),
                          db.lastError().text());
  }

  QSqlDatabase::removeDatabase("testdb");
}

void DbDialog::toggleConnection()
{
  DbManager::toggle(DbManager::getDatabase(
      dbListView->selectionModel()->selectedIndexes()[0].row()));
}
<commit_msg>Bogue test connexion<commit_after>/*
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; version 3 of the License.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 */

#include "../dbmanager.h"
#include "../iconmanager.h"
#include "../wizards/newdbwizard.h"

#include "dbdialog.h"

DbDialog::DbDialog(QWidget *parent)
  : QDialog(parent)
{
  setupUi(this);
  setupWidgets();
  setupConnections();

  db = NULL;
  reload();
}

void DbDialog::accept()
{
  if(db->isOpen()) {
    close();
    return;
  }

  apply();

  QDialog::accept();
  close();
}

void DbDialog::apply() {
  if(db->isOpen()) {
    return;
  }

  db->setHostName(hostEdit->text());
  db->setUserName(userEdit->text());
  db->setPassword(passEdit->text());
  db->setDatabaseName(dbEdit->text());

  DbManager::update(db);
}

/**
 * Forwards the signal from NewDbWizard to MainWindow.
 */
void DbDialog::forwardAccept()
{
}

void DbDialog::refresh(QModelIndex index)
{
  if(dbListView->selectionModel()->selectedRows().contains(index))
    reload();
}

/**
 * Re-fills all fields and enables/disables widgets
 */
void DbDialog::reload()
{
  bool emptyList = DbManager::getDbList().size() == 0;
  bool selected = !emptyList
                  && dbListView->selectionModel()->selection().size() > 0;
  bool open = selected && db->isOpen();

  groupBox->setEnabled(selected && !open);
  toggleButton->setEnabled(selected);
  remButton->setEnabled(selected);

  if(open)
  {
    toggleButton->setIcon(IconManager::get("connect_no"));
    toggleButton->setText(tr("Disconnect"));
  }
  else
  {
    toggleButton->setIcon(IconManager::get("connect_creating"));
    toggleButton->setText(tr("Connect"));
  }

  if(DbManager::getDbList().size() > 0 && db)
  {
    hostEdit->setText(db->hostName());
    userEdit->setText(db->userName());
    saveCheckBox->setChecked(!open && !db->password().isEmpty());
    passEdit->setText(db->password());
    dbTypeComboBox->setCurrentDriver(db->driverName());
    dbEdit->setText(db->databaseName());
  }

  dbBrowseButton->setVisible(false);
  resultLabel->setText(tr("<- Click to test"));
}

void DbDialog::removeCurrent()
{
  int index = dbListView->currentIndex().row();
  if(DbManager::getDatabase(index)->isOpen())
  {
    QMessageBox::critical(this,
                          tr("Cannot remove"),
                          tr("You must close the database before remove it.")
                          );
    return;
  }
  DbManager::removeDatabase(index);
  reload();
}

/**
 * Must be called to enter the Edit mode
 */
void DbDialog::setDatabase(QModelIndex index)
{
  QItemSelectionModel *m = dbListView->selectionModel();
  m->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
  db = DbManager::getDatabase(index.row());

  reload();
}

void DbDialog::setupConnections()
{
  // buttons
  connect(addButton,    SIGNAL(clicked()), addWzd,  SLOT(exec()));
  connect(remButton,    SIGNAL(clicked()), this,    SLOT(removeCurrent()));
  connect(testButton,   SIGNAL(clicked()), this,    SLOT(testConnection()));
  connect(toggleButton, SIGNAL(clicked()), this,    SLOT(toggleConnection()));
  connect(buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()),
          this, SLOT(apply()));
  connect(buttonBox->button(QDialogButtonBox::Reset), SIGNAL(clicked()),
          this, SLOT(reload()));

  // list view
  connect(dbListView, SIGNAL(clicked(QModelIndex)),
          this, SLOT(setDatabase(QModelIndex)));

  connect(addWzd, SIGNAL(accepted()), this, SLOT(forwardAccept()));

  connect(DbManager::instance(), SIGNAL(statusChanged(QModelIndex)),
          this, SLOT(refresh(QModelIndex)));
}

void DbDialog::setupWidgets()
{
  addWzd = new NewDbWizard(this);
  dbBrowseButton->setVisible(false);
  dbListView->setModel(DbManager::model());

  QCompleter *c = new QCompleter(QStringList("localhost"), this);
  c->setCompletionMode(QCompleter::InlineCompletion);
  hostEdit->setCompleter(c);

  // loading icons from theme
  addButton->setIcon(IconManager::get("list-add"));
  remButton->setIcon(IconManager::get("list-remove"));
//  hostLabel->setPixmap(IconManager::get("network-server")
//                       .pixmap(QSize(32, 32)));
//  userLabel->setPixmap(IconManager::get("user-info")
//                         .pixmap(QSize(32, 32)));
//  pswdLabel->setPixmap(IconManager::get("dialog-password")
//                         .pixmap(QSize(32, 32)));
  toggleButton->setIcon(IconManager::get("connect_creating"));
}

void DbDialog::testConnection()
{
  QSqlDatabase db = QSqlDatabase::addDatabase(
      dbTypeComboBox->currentDriverName(), "testdb");
  db.setHostName(hostEdit->text());
  db.setUserName(userEdit->text());
  db.setPassword(passEdit->text());
  db.setDatabaseName(dbEdit->text());

  if(db.open())
  {
    resultLabel->setText(tr("Connection succeded"));
  }
  else
  {
    resultLabel->setText(tr("Connection failed"));
    QMessageBox::critical(this,
                          tr("Connection failed"),
                          db.lastError().text());
  }

  QSqlDatabase::removeDatabase("testdb");
}

void DbDialog::toggleConnection()
{
  DbManager::toggle(DbManager::getDatabase(
      dbListView->selectionModel()->selectedIndexes()[0].row()));
}
<|endoftext|>


<commit_before>#define _CRT_SECURE_NO_WARNINGS

#include "UserActions.h"
#include <fstream>
using std::ifstream;

#include <cstring>

const int MAX_CHAR_COMMAND = 128;
const int MAX_CHARS_PER_LINE = 134; // 128 + 6
const char* const DELIMITER = ";";

UserActions::UserActions() : m_mMappings({}) {}

void UserActions::add(std::string name, Command c) {
	if (!m_mMappings.count(name)) {
		std::vector<Command> tempCommands;
		m_mMappings[name] = tempCommands;
	}

	m_mMappings[name].push_back(c);
}

int UserActions::getActionState(std::string name) {
	if (!m_mMappings.count(name)) {
		return 0;
	}

	std::vector<Command> commands = m_mMappings[name];
	int ret = 0;
	InputHandler* handlerInstance = InputHandler::Instance();
	for (unsigned int c = 0; c < commands.size(); c++) {
		switch (commands[c].type) {
			case CONTROLLER_BUTTON:
				ret = !handlerInstance->joysticksInitialised() ? 0 :
					handlerInstance->getButtonState(0, commands[c].buttonId);
				break;
			case CONTROLLER_STICK:
				if (handlerInstance->joysticksInitialised()) {
					int stickValue = handlerInstance->stickValue(
						0, commands[c].stickAxis
					);
					int stickDirection = commands[c].stickDirection;
					if (stickDirection == 0 || stickValue == stickDirection) {
						ret = stickValue;
					}
				}
				break;
			case KEYBOARD_KEY:
				ret = handlerInstance->getKeyState(commands[c].key);
				break;
			case NULL_TYPE:
			default:
				break;
		}

		if (ret != 0) {
			break;
		}
	}

	return ret;
}

void UserActions::resetActionState(std::string name) {
	if (!m_mMappings.count(name)) {
		return;
	}

	std::vector<Command> commands = m_mMappings[name];
	InputHandler* handlerInstance = InputHandler::Instance();
	for (unsigned int c = 0; c < commands.size(); c++) {
		switch (commands[c].type) {
			case CONTROLLER_BUTTON:
				if (handlerInstance->joysticksInitialised()) {
					handlerInstance->setButtonState(
						0, commands[c].buttonId, false
					);
				}
				break;
			case KEYBOARD_KEY:
				handlerInstance->setKeyState(commands[c].key, false);
				break;
			case CONTROLLER_STICK:
			case NULL_TYPE:
			default:
				break;
		}
	}
}

int UserActions::setActionsFromFile(const char* mappingFile) {
	// create a file-reading object
	ifstream fin;
	fin.open(mappingFile); // open a file
	if (!fin.good()) {
		return NO_FILE_FOUND; // exit if file not found
	}

	// read each line of the file
	while (!fin.eof()) {
		// read an entire line into memory
		char buf[MAX_CHARS_PER_LINE];
		// @check too long lines
		fin.getline(buf, MAX_CHARS_PER_LINE);

		if (buf[0] == '\0' || buf[0] == '#') {
			continue;
		}

		char commandName[MAX_CHAR_COMMAND];
		char* token;
		InputType type;
		int value,
			direction = 0;

		// @TODO Check buffer overflow
		token = strtok(buf, DELIMITER);
		strncpy(commandName, token, MAX_CHAR_COMMAND);

		// @TODO check missing values
		token = strtok(0, DELIMITER);
		if (token == 0) {
			return NO_TYPE_FOUND;
		}

		type = (InputType) atoi(token);
		token = strtok(0, DELIMITER);
		if (token == 0) {
			return NO_VALUE_FOUND;
		}

		value = atoi(token);
		token = strtok(0, DELIMITER);

		if (token != 0) {
			direction = atoi(token);
		}

		Command c;
		c.type = type;
		switch (type) {
			case KEYBOARD_KEY:
				c.key = (SDL_Scancode) value;
				break;
			case CONTROLLER_BUTTON:
				c.buttonId = (unsigned long) value;
				break;
			case CONTROLLER_STICK:
				c.stickAxis = (JoystickControl) value;
				c.stickDirection = direction;
				break;
			case NULL_TYPE:
			default:
				return INVALID_TYPE;
		}
		add(commandName, c);
	}

	return 0;
}
<commit_msg>NULL_TYPE is different than invalid type<commit_after>#define _CRT_SECURE_NO_WARNINGS

#include "UserActions.h"
#include <fstream>
using std::ifstream;

#include <cstring>

const int MAX_CHAR_COMMAND = 128;
const int MAX_CHARS_PER_LINE = 134; // 128 + 6
const char* const DELIMITER = ";";

UserActions::UserActions() : m_mMappings({}) {}

void UserActions::add(std::string name, Command c) {
	if (!m_mMappings.count(name)) {
		std::vector<Command> tempCommands;
		m_mMappings[name] = tempCommands;
	}

	m_mMappings[name].push_back(c);
}

int UserActions::getActionState(std::string name) {
	if (!m_mMappings.count(name)) {
		return 0;
	}

	std::vector<Command> commands = m_mMappings[name];
	int ret = 0;
	InputHandler* handlerInstance = InputHandler::Instance();
	for (unsigned int c = 0; c < commands.size(); c++) {
		switch (commands[c].type) {
			case CONTROLLER_BUTTON:
				ret = !handlerInstance->joysticksInitialised() ? 0 :
					handlerInstance->getButtonState(0, commands[c].buttonId);
				break;
			case CONTROLLER_STICK:
				if (handlerInstance->joysticksInitialised()) {
					int stickValue = handlerInstance->stickValue(
						0, commands[c].stickAxis
					);
					int stickDirection = commands[c].stickDirection;
					if (stickDirection == 0 || stickValue == stickDirection) {
						ret = stickValue;
					}
				}
				break;
			case KEYBOARD_KEY:
				ret = handlerInstance->getKeyState(commands[c].key);
				break;
			case NULL_TYPE:
			default:
				break;
		}

		if (ret != 0) {
			break;
		}
	}

	return ret;
}

void UserActions::resetActionState(std::string name) {
	if (!m_mMappings.count(name)) {
		return;
	}

	std::vector<Command> commands = m_mMappings[name];
	InputHandler* handlerInstance = InputHandler::Instance();
	for (unsigned int c = 0; c < commands.size(); c++) {
		switch (commands[c].type) {
			case CONTROLLER_BUTTON:
				if (handlerInstance->joysticksInitialised()) {
					handlerInstance->setButtonState(
						0, commands[c].buttonId, false
					);
				}
				break;
			case KEYBOARD_KEY:
				handlerInstance->setKeyState(commands[c].key, false);
				break;
			case CONTROLLER_STICK:
			case NULL_TYPE:
			default:
				break;
		}
	}
}

int UserActions::setActionsFromFile(const char* mappingFile) {
	// create a file-reading object
	ifstream fin;
	fin.open(mappingFile); // open a file
	if (!fin.good()) {
		return NO_FILE_FOUND; // exit if file not found
	}

	// read each line of the file
	while (!fin.eof()) {
		// read an entire line into memory
		char buf[MAX_CHARS_PER_LINE];
		// @check too long lines
		fin.getline(buf, MAX_CHARS_PER_LINE);

		if (buf[0] == '\0' || buf[0] == '#') {
			continue;
		}

		char commandName[MAX_CHAR_COMMAND];
		char* token;
		InputType type;
		int value,
			direction = 0;

		// @TODO Check buffer overflow
		token = strtok(buf, DELIMITER);
		strncpy(commandName, token, MAX_CHAR_COMMAND);

		// @TODO check missing values
		token = strtok(0, DELIMITER);
		if (token == 0) {
			return NO_TYPE_FOUND;
		}

		type = (InputType) atoi(token);
		token = strtok(0, DELIMITER);
		if (token == 0) {
			return NO_VALUE_FOUND;
		}

		value = atoi(token);
		token = strtok(0, DELIMITER);

		if (token != 0) {
			direction = atoi(token);
		}

		Command c;
		c.type = type;
		switch (type) {
			case KEYBOARD_KEY:
				c.key = (SDL_Scancode) value;
				break;
			case CONTROLLER_BUTTON:
				c.buttonId = (unsigned long) value;
				break;
			case CONTROLLER_STICK:
				c.stickAxis = (JoystickControl) value;
				c.stickDirection = direction;
				break;
			case NULL_TYPE:
				break;
			default:
				return INVALID_TYPE;
		}
		add(commandName, c);
	}

	return 0;
}
<|endoftext|>


<commit_before>/*!
 *  Copyright (c) 2017 by Contributors
 * \file precompute_prune.cc
 * \brief Split the graph into a pre-compute graph and a execution graph.
 *
 *  The pre-compute graph outputs parameters that can be taken
 *  by execution graph during execution phase.
 */
#include <nnvm/graph.h>
#include <nnvm/op_attr_types.h>
#include <nnvm/graph_attr_types.h>
#include <nnvm/pass.h>
#include <nnvm/compiler/op_attr_types.h>
#include <unordered_set>

namespace nnvm {
namespace compiler {

nnvm::Graph PrecomputePrune(nnvm::Graph src) {
  const auto& plist
      = src.GetAttr<std::vector<std::string> >("param_name_list");
  std::unordered_set<std::string> params(plist.begin(), plist.end());

  std::unordered_set<nnvm::Node*> pruned;
  nnvm::NodeEntryMap<nnvm::NodePtr> entry_var;
  std::unordered_set<std::string> unique_name;
  // number of edges that are not variable
  int non_var_edge = 0;

  DFSVisit(src.outputs, [&](const nnvm::NodePtr& n) {
    bool can_be_pruned = true;
    if (n->is_variable()) {
      if (params.count(n->attrs.name)) {
        pruned.emplace(n.get());
      }
      can_be_pruned = false;
    }

    for (const auto& e : n->inputs) {
      if (!pruned.count(e.node.get())) {
        can_be_pruned = false;
      }
    }
    if (can_be_pruned) {
      pruned.emplace(n.get());
    } else {
      // scan again to find edge nodes, skip variables
      for (auto& e : n->inputs) {
        if (pruned.count(e.node.get())) {
          if (!entry_var.count(e)) {
            if (!e.node->is_variable()) {
              ++non_var_edge;
            }
            nnvm::NodePtr var = nnvm::Node::Create();
            var->attrs.name = e.node->attrs.name;
            if (e.node->num_outputs() != 1) {
              var->attrs.name += "_output" + std::to_string(e.index);
            }
            entry_var.emplace(e, var);
            CHECK(!unique_name.count(var->attrs.name));
            unique_name.insert(var->attrs.name);
          }
          e = nnvm::NodeEntry{entry_var.at(e), 0, 0};
        }
      }
    }
  });

  // nothing being pruned.
  if (non_var_edge == 0) {
    return src;
  }

  nnvm::Graph pre_graph;
  pre_graph.outputs.reserve(entry_var.size());
  std::vector<std::string> output_names;
  output_names.reserve(entry_var.size());

  for (auto kv : entry_var) {
    pre_graph.outputs.emplace_back(kv.first);
    output_names.emplace_back(kv.second->attrs.name);
  }
  // new parameter list
  pre_graph.attrs["output_names"] =
      std::make_shared<dmlc::any>(std::move(output_names));
  src.attrs["precompute_graph"] =
      std::make_shared<dmlc::any>(std::move(pre_graph));
  return src;
}

NNVM_REGISTER_PASS(PrecomputePrune)
.set_body(PrecomputePrune);
}  // namespace compiler
}  // namespace nnvm
<commit_msg>[OPT] Improve PreComputePrune When Output Is Pruned (#178)<commit_after>/*!
 *  Copyright (c) 2017 by Contributors
 * \file precompute_prune.cc
 * \brief Split the graph into a pre-compute graph and a execution graph.
 *
 *  The pre-compute graph outputs parameters that can be taken
 *  by execution graph during execution phase.
 */
#include <nnvm/graph.h>
#include <nnvm/op_attr_types.h>
#include <nnvm/graph_attr_types.h>
#include <nnvm/pass.h>
#include <nnvm/compiler/op_attr_types.h>
#include <unordered_set>

namespace nnvm {
namespace compiler {

nnvm::Graph PrecomputePrune(nnvm::Graph src) {
  const auto& plist
      = src.GetAttr<std::vector<std::string> >("param_name_list");
  std::unordered_set<std::string> params(plist.begin(), plist.end());

  std::unordered_set<nnvm::Node*> pruned;
  nnvm::NodeEntryMap<nnvm::NodePtr> entry_var;
  std::unordered_set<std::string> unique_name;
  // number of edges that are not variable
  int non_var_edge = 0;

  auto replace_pruned_entry = [&] (const NodeEntry& e) {
    if (!entry_var.count(e)) {
      if (!e.node->is_variable()) {
        ++non_var_edge;
      }
      nnvm::NodePtr var = nnvm::Node::Create();
      var->attrs.name = e.node->attrs.name;
      if (e.node->num_outputs() != 1) {
        var->attrs.name += "_output" + std::to_string(e.index);
      }
      entry_var.emplace(e, var);
      CHECK(!unique_name.count(var->attrs.name));
      unique_name.insert(var->attrs.name);
      return nnvm::NodeEntry{var, 0, 0};
    } else {
      return nnvm::NodeEntry{entry_var.at(e), 0, 0};
    }
  };

  DFSVisit(src.outputs, [&](const nnvm::NodePtr& n) {
    bool can_be_pruned = true;
    if (n->is_variable()) {
      if (params.count(n->attrs.name)) {
        pruned.emplace(n.get());
      }
      can_be_pruned = false;
    }

    for (const auto& e : n->inputs) {
      if (!pruned.count(e.node.get())) {
        can_be_pruned = false;
      }
    }
    if (can_be_pruned) {
      pruned.emplace(n.get());
    } else {
      // scan again to find edge nodes, skip variables
      for (auto& e : n->inputs) {
        if (pruned.count(e.node.get())) {
          e = replace_pruned_entry(e);
        }
      }
    }
  });

  // nothing being pruned.
  if (non_var_edge == 0) {
    return src;
  }

  for (auto& e : src.outputs) {
    if (pruned.count(e.node.get())) {
      e = replace_pruned_entry(e);
    }
  }

  nnvm::Graph pre_graph;
  pre_graph.outputs.reserve(entry_var.size());
  std::vector<std::string> output_names;
  output_names.reserve(entry_var.size());

  for (auto kv : entry_var) {
    pre_graph.outputs.emplace_back(kv.first);
    output_names.emplace_back(kv.second->attrs.name);
  }
  // new parameter list
  pre_graph.attrs["output_names"] =
      std::make_shared<dmlc::any>(std::move(output_names));
  src.attrs["precompute_graph"] =
      std::make_shared<dmlc::any>(std::move(pre_graph));
  return src;
}

NNVM_REGISTER_PASS(PrecomputePrune)
.set_body(PrecomputePrune);
}  // namespace compiler
}  // namespace nnvm
<|endoftext|>


<commit_before>// led means focus triggered

#include "mbed.h"
//#include "serial_api.h"

DigitalOut led(LED1); // PA_5
InterruptIn button(USER_BUTTON); // PC_13

BusOut shutter(
		PC_9, // 1/A
		PB_9, // 2/B
		PA_7, // 3/C
		PC_7, // 4/D
		PA_8, // 5/E
		PC_8, // 6/F
		PC_5, // 7/G
		PA_11,// 8/H
		PB_2, // 9/I
		PB_15 //10/J
);
BusOut focus(
		PB_8, // 1/A
		PA_6, // 2/B
		PB_6, // 3/C
		PA_9, // 4/D
		PB_10,// 5/E
		PC_6, // 6/F
		PA_12,// 7/G
		PB_12,// 8/H
		PB_1, // 9/I
		PB_14 //10/J
);

const int MASK = 0x3ff; // 10 bits

Serial ser(SERIAL_TX, SERIAL_RX);

#define STATE_NONE 0
#define STATE_FOCUS 1
#define STATE_SHOOT 2
#define STATE_RESET 3

volatile int recvstate; // start at none
volatile int recvmask;
int workmask;
int workstate;

void recvfunc() {
	int c = ser.getc();
	ser.putc(c);
	switch (c) {
	case '1':
		workmask <<= 1;
		workmask |= 1;
		break;
	case '0':
		workmask <<= 1;
		break;
	case 'F':
		workstate = STATE_FOCUS;
		break;
	case 'S':
		workstate = STATE_SHOOT;
		break;
	case 'R':
		workmask = 0;
		recvmask = 0;
		workstate = STATE_RESET;
		recvstate = workstate;
		break;
	case ' ': /* fallthrough */
	case '\r':
		recvmask = workmask;
		recvstate = workstate;
		workmask = 0;
		break;
	}
}

void butnfunc() {
	if (focus == 0) {
		focus = MASK;
	} else {
		shutter = MASK;
		wait(0.2);
		shutter = 0;
	}
}

int main() {
	// bootup signal
	for (int i = 0; i < 3; i++) {
		led = 1;
		wait(0.1);
		led = 0;
		wait(0.1);
	}

	focus = 0;
	shutter = 0;
	led = 0;

	ser.attach(recvfunc, Serial::RxIrq);
	button.fall(butnfunc);

	for (;;) {
		int st, rmask;
		while ((st = recvstate) == STATE_NONE) {
			// wait
		}
		rmask = recvmask;
		recvstate = STATE_NONE;

		switch (st) {
		case STATE_FOCUS:
			if (rmask)
				led = 1;
			focus = rmask & MASK;
			break;
		case STATE_SHOOT:
			shutter = rmask & MASK;
			break;
		case STATE_RESET:
			focus = 0;
			shutter = 0;
			led = 0;
			break;
		}
	}
}
<commit_msg>mbed: pcshot: add debounce after focus button<commit_after>// led means focus triggered

#include "mbed.h"
//#include "serial_api.h"

DigitalOut led(LED1); // PA_5
InterruptIn button(USER_BUTTON); // PC_13

BusOut shutter(
		PC_9, // 1/A
		PB_9, // 2/B
		PA_7, // 3/C
		PC_7, // 4/D
		PA_8, // 5/E
		PC_8, // 6/F
		PC_5, // 7/G
		PA_11,// 8/H
		PB_2, // 9/I
		PB_15 //10/J
);
BusOut focus(
		PB_8, // 1/A
		PA_6, // 2/B
		PB_6, // 3/C
		PA_9, // 4/D
		PB_10,// 5/E
		PC_6, // 6/F
		PA_12,// 7/G
		PB_12,// 8/H
		PB_1, // 9/I
		PB_14 //10/J
);

const int MASK = 0x3ff; // 10 bits

Serial ser(SERIAL_TX, SERIAL_RX);

#define STATE_NONE 0
#define STATE_FOCUS 1
#define STATE_SHOOT 2
#define STATE_RESET 3

volatile int recvstate; // start at none
volatile int recvmask;
int workmask;
int workstate;

void recvfunc() {
	int c = ser.getc();
	ser.putc(c);
	switch (c) {
	case '1':
		workmask <<= 1;
		workmask |= 1;
		break;
	case '0':
		workmask <<= 1;
		break;
	case 'F':
		workstate = STATE_FOCUS;
		break;
	case 'S':
		workstate = STATE_SHOOT;
		break;
	case 'R':
		workmask = 0;
		recvmask = 0;
		workstate = STATE_RESET;
		recvstate = workstate;
		break;
	case ' ': /* fallthrough */
	case '\r':
		recvmask = workmask;
		recvstate = workstate;
		workmask = 0;
		break;
	}
}

void butnfunc() {
	if (focus == 0) {
		focus = MASK;
		wait(0.2); // debounce
	} else {
		shutter = MASK;
		wait(0.2);
		shutter = 0;
	}
}

int main() {
	// bootup signal
	for (int i = 0; i < 3; i++) {
		led = 1;
		wait(0.1);
		led = 0;
		wait(0.1);
	}

	focus = 0;
	shutter = 0;
	led = 0;

	ser.attach(recvfunc, Serial::RxIrq);
	button.fall(butnfunc);

	for (;;) {
		int st, rmask;
		while ((st = recvstate) == STATE_NONE) {
			// wait
		}
		rmask = recvmask;
		recvstate = STATE_NONE;

		switch (st) {
		case STATE_FOCUS:
			if (rmask)
				led = 1;
			focus = rmask & MASK;
			break;
		case STATE_SHOOT:
			shutter = rmask & MASK;
			break;
		case STATE_RESET:
			focus = 0;
			shutter = 0;
			led = 0;
			break;
		}
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012-2014 ARM Limited
 * All rights reserved.
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2003-2005,2014 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER 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.
 *
 * Authors: Erik Hallnor
 */

/**
 * @file
 * Definitions of a base set associative tag store.
 */

#include "mem/cache/tags/base_set_assoc.hh"

#include <string>

#include "base/intmath.hh"
#include "sim/core.hh"

using namespace std;

BaseSetAssoc::BaseSetAssoc(const Params *p)
    :BaseTags(p), assoc(p->assoc), allocAssoc(p->assoc),
     numSets(p->size / (p->block_size * p->assoc)),
     sequentialAccess(p->sequential_access)
{
    // Check parameters
    if (blkSize < 4 || !isPowerOf2(blkSize)) {
        fatal("Block size must be at least 4 and a power of 2");
    }
    if (numSets <= 0 || !isPowerOf2(numSets)) {
        fatal("# of sets must be non-zero and a power of 2");
    }
    if (assoc <= 0) {
        fatal("associativity must be greater than zero");
    }

    setShift = floorLog2(blkSize);
    setMask = numSets - 1;
    tagShift = setShift + floorLog2(numSets);
    /** @todo Make warmup percentage a parameter. */
    warmupBound = numSets * assoc;

    sets = new SetType[numSets];
    blks = new BlkType[numSets * assoc];
    // allocate data storage in one big chunk
    numBlocks = numSets * assoc;
    dataBlks = new uint8_t[numBlocks * blkSize];

    unsigned blkIndex = 0;       // index into blks array
    for (unsigned i = 0; i < numSets; ++i) {
        sets[i].assoc = assoc;

        sets[i].blks = new BlkType*[assoc];

        // link in the data blocks
        for (unsigned j = 0; j < assoc; ++j) {
            // locate next cache block
            BlkType *blk = &blks[blkIndex];
            blk->data = &dataBlks[blkSize*blkIndex];
            ++blkIndex;

            // invalidate new cache block
            blk->invalidate();

            //EGH Fix Me : do we need to initialize blk?

            // Setting the tag to j is just to prevent long chains in the hash
            // table; won't matter because the block is invalid
            blk->tag = j;
            blk->whenReady = 0;
            blk->isTouched = false;
            sets[i].blks[j]=blk;
            blk->set = i;
            blk->way = j;
        }
    }
}

BaseSetAssoc::~BaseSetAssoc()
{
    delete [] dataBlks;
    delete [] blks;
    delete [] sets;
}

CacheBlk*
BaseSetAssoc::findBlock(Addr addr, bool is_secure) const
{
    Addr tag = extractTag(addr);
    unsigned set = extractSet(addr);
    BlkType *blk = sets[set].findBlk(tag, is_secure);
    return blk;
}

CacheBlk*
BaseSetAssoc::findBlockBySetAndWay(int set, int way) const
{
    return sets[set].blks[way];
}

std::string
BaseSetAssoc::print() const {
    std::string cache_state;
    for (unsigned i = 0; i < numSets; ++i) {
        // link in the data blocks
        for (unsigned j = 0; j < assoc; ++j) {
            BlkType *blk = sets[i].blks[j];
            if (blk->isValid())
                cache_state += csprintf("\tset: %d block: %d %s\n", i, j,
                        blk->print());
        }
    }
    if (cache_state.empty())
        cache_state = "no valid tags\n";
    return cache_state;
}

void
BaseSetAssoc::cleanupRefs()
{
    for (unsigned i = 0; i < numSets*assoc; ++i) {
        if (blks[i].isValid()) {
            totalRefs += blks[i].refCount;
            ++sampledRefs;
        }
    }
}

void
BaseSetAssoc::computeStats()
{
    for (unsigned i = 0; i < ContextSwitchTaskId::NumTaskId; ++i) {
        occupanciesTaskId[i] = 0;
        for (unsigned j = 0; j < 5; ++j) {
            ageTaskId[i][j] = 0;
        }
    }

    for (unsigned i = 0; i < numSets * assoc; ++i) {
        if (blks[i].isValid()) {
            assert(blks[i].task_id < ContextSwitchTaskId::NumTaskId);
            occupanciesTaskId[blks[i].task_id]++;
            assert(blks[i].tickInserted <= curTick());
            Tick age = curTick() - blks[i].tickInserted;

            int age_index;
            if (age / SimClock::Int::us < 10) { // <10us
                age_index = 0;
            } else if (age / SimClock::Int::us < 100) { // <100us
                age_index = 1;
            } else if (age / SimClock::Int::ms < 1) { // <1ms
                age_index = 2;
            } else if (age / SimClock::Int::ms < 10) { // <10ms
                age_index = 3;
            } else
                age_index = 4; // >10ms

            ageTaskId[blks[i].task_id][age_index]++;
        }
    }
}
<commit_msg>mem-cache: Remove extra numSets zero check.<commit_after>/*
 * Copyright (c) 2012-2014 ARM Limited
 * All rights reserved.
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Copyright (c) 2003-2005,2014 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER 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.
 *
 * Authors: Erik Hallnor
 */

/**
 * @file
 * Definitions of a base set associative tag store.
 */

#include "mem/cache/tags/base_set_assoc.hh"

#include <string>

#include "base/intmath.hh"
#include "sim/core.hh"

using namespace std;

BaseSetAssoc::BaseSetAssoc(const Params *p)
    :BaseTags(p), assoc(p->assoc), allocAssoc(p->assoc),
     numSets(p->size / (p->block_size * p->assoc)),
     sequentialAccess(p->sequential_access)
{
    // Check parameters
    if (blkSize < 4 || !isPowerOf2(blkSize)) {
        fatal("Block size must be at least 4 and a power of 2");
    }
    if (!isPowerOf2(numSets)) {
        fatal("# of sets must be non-zero and a power of 2");
    }
    if (assoc <= 0) {
        fatal("associativity must be greater than zero");
    }

    setShift = floorLog2(blkSize);
    setMask = numSets - 1;
    tagShift = setShift + floorLog2(numSets);
    /** @todo Make warmup percentage a parameter. */
    warmupBound = numSets * assoc;

    sets = new SetType[numSets];
    blks = new BlkType[numSets * assoc];
    // allocate data storage in one big chunk
    numBlocks = numSets * assoc;
    dataBlks = new uint8_t[numBlocks * blkSize];

    unsigned blkIndex = 0;       // index into blks array
    for (unsigned i = 0; i < numSets; ++i) {
        sets[i].assoc = assoc;

        sets[i].blks = new BlkType*[assoc];

        // link in the data blocks
        for (unsigned j = 0; j < assoc; ++j) {
            // locate next cache block
            BlkType *blk = &blks[blkIndex];
            blk->data = &dataBlks[blkSize*blkIndex];
            ++blkIndex;

            // invalidate new cache block
            blk->invalidate();

            //EGH Fix Me : do we need to initialize blk?

            // Setting the tag to j is just to prevent long chains in the hash
            // table; won't matter because the block is invalid
            blk->tag = j;
            blk->whenReady = 0;
            blk->isTouched = false;
            sets[i].blks[j]=blk;
            blk->set = i;
            blk->way = j;
        }
    }
}

BaseSetAssoc::~BaseSetAssoc()
{
    delete [] dataBlks;
    delete [] blks;
    delete [] sets;
}

CacheBlk*
BaseSetAssoc::findBlock(Addr addr, bool is_secure) const
{
    Addr tag = extractTag(addr);
    unsigned set = extractSet(addr);
    BlkType *blk = sets[set].findBlk(tag, is_secure);
    return blk;
}

CacheBlk*
BaseSetAssoc::findBlockBySetAndWay(int set, int way) const
{
    return sets[set].blks[way];
}

std::string
BaseSetAssoc::print() const {
    std::string cache_state;
    for (unsigned i = 0; i < numSets; ++i) {
        // link in the data blocks
        for (unsigned j = 0; j < assoc; ++j) {
            BlkType *blk = sets[i].blks[j];
            if (blk->isValid())
                cache_state += csprintf("\tset: %d block: %d %s\n", i, j,
                        blk->print());
        }
    }
    if (cache_state.empty())
        cache_state = "no valid tags\n";
    return cache_state;
}

void
BaseSetAssoc::cleanupRefs()
{
    for (unsigned i = 0; i < numSets*assoc; ++i) {
        if (blks[i].isValid()) {
            totalRefs += blks[i].refCount;
            ++sampledRefs;
        }
    }
}

void
BaseSetAssoc::computeStats()
{
    for (unsigned i = 0; i < ContextSwitchTaskId::NumTaskId; ++i) {
        occupanciesTaskId[i] = 0;
        for (unsigned j = 0; j < 5; ++j) {
            ageTaskId[i][j] = 0;
        }
    }

    for (unsigned i = 0; i < numSets * assoc; ++i) {
        if (blks[i].isValid()) {
            assert(blks[i].task_id < ContextSwitchTaskId::NumTaskId);
            occupanciesTaskId[blks[i].task_id]++;
            assert(blks[i].tickInserted <= curTick());
            Tick age = curTick() - blks[i].tickInserted;

            int age_index;
            if (age / SimClock::Int::us < 10) { // <10us
                age_index = 0;
            } else if (age / SimClock::Int::us < 100) { // <100us
                age_index = 1;
            } else if (age / SimClock::Int::ms < 1) { // <1ms
                age_index = 2;
            } else if (age / SimClock::Int::ms < 10) { // <10ms
                age_index = 3;
            } else
                age_index = 4; // >10ms

            ageTaskId[blks[i].task_id][age_index]++;
        }
    }
}
<|endoftext|>