<commit_before>#include "InputManager.h"
#include "InputConfig.h"
#include "Settings.h"
#include "Window.h"
#include "Log.h"
#include "pugixml/pugixml.hpp"
#include <boost/filesystem.hpp>
#include "platform.h"

#define KEYBOARD_GUID_STRING "-1"

// SO HEY POTENTIAL POOR SAP WHO IS TRYING TO MAKE SENSE OF ALL THIS (by which I mean my future self)
// There are like four distinct IDs used for joysticks (crazy, right?)
// 1. Device index - this is the "lowest level" identifier, and is just the Nth joystick plugged in to the system (like /dev/js#).
//    It can change even if the device is the same, and is only used to open joysticks (required to receive SDL events).
// 2. SDL_JoystickID - this is an ID for each joystick that is supposed to remain consistent between plugging and unplugging.
//    ES doesn't care if it does, though.
// 3. "Device ID" - this is something I made up and is what InputConfig's getDeviceID() returns.
//    This is actually just an SDL_JoystickID (also called instance ID), but -1 means "keyboard" instead of "error."
// 4. Joystick GUID - this is some squashed version of joystick vendor, version, and a bunch of other device-specific things.
//    It should remain the same across runs of the program/system restarts/device reordering and is what I use to identify which joystick to load.

namespace fs = boost::filesystem;

InputManager* InputManager::mInstance = NULL;

InputManager::InputManager() : mKeyboardInputConfig(NULL)
{
}

InputManager::~InputManager()
{
	deinit();
}

InputManager* InputManager::getInstance()
{
	if(!mInstance)
		mInstance = new InputManager();

	return mInstance;
}

void InputManager::init()
{
	if(initialized())
		deinit();

	if (Settings::getInstance()->getBool("BackgroundJoystickInput")){
		SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
	}
	SDL_InitSubSystem(SDL_INIT_JOYSTICK);
	SDL_JoystickEventState(SDL_ENABLE);

	// first, open all currently present joysticks
	int numJoysticks = SDL_NumJoysticks();
	for(int i = 0; i < numJoysticks; i++)
	{
		addJoystickByDeviceIndex(i);
	}

	mKeyboardInputConfig = new InputConfig(DEVICE_KEYBOARD, "Keyboard", KEYBOARD_GUID_STRING);
	loadInputConfig(mKeyboardInputConfig);
}

void InputManager::addJoystickByDeviceIndex(int id)
{
	assert(id >= 0 && id < SDL_NumJoysticks());

	// open joystick & add to our list
	SDL_Joystick* joy = SDL_JoystickOpen(id);
	assert(joy);

	// add it to our list so we can close it again later
	SDL_JoystickID joyId = SDL_JoystickInstanceID(joy);
	mJoysticks[joyId] = joy;

	char guid[65];
	SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joy), guid, 65);

	// create the InputConfig
	mInputConfigs[joyId] = new InputConfig(joyId, SDL_JoystickName(joy), guid);
	if(!loadInputConfig(mInputConfigs[joyId]))
	{
		LOG(LogInfo) << "Added unconfigured joystick " << SDL_JoystickName(joy) << " (GUID: " << guid << ", instance ID: " << joyId << ", device index: " << id << ").";
	}else{
		LOG(LogInfo) << "Added known joystick " << SDL_JoystickName(joy) << " (instance ID: " << joyId << ", device index: " << id << ")";
	}

	// set up the prevAxisValues
	int numAxes = SDL_JoystickNumAxes(joy);
	mPrevAxisValues[joyId] = new int[numAxes];
	std::fill(mPrevAxisValues[joyId], mPrevAxisValues[joyId] + numAxes, 0); //initialize array to 0
}

void InputManager::removeJoystickByJoystickID(SDL_JoystickID joyId)
{
	assert(joyId != -1);

	// delete old prevAxisValues
	auto axisIt = mPrevAxisValues.find(joyId);
	delete[] axisIt->second;
	mPrevAxisValues.erase(axisIt);

	// delete old InputConfig
	auto it = mInputConfigs.find(joyId);
	delete it->second;
	mInputConfigs.erase(it);

	// close the joystick
	auto joyIt = mJoysticks.find(joyId);
	if(joyIt != mJoysticks.end())
	{
		SDL_JoystickClose(joyIt->second);
		mJoysticks.erase(joyIt);
	}else{
		LOG(LogError) << "Could not find joystick to close (instance ID: " << joyId << ")";
	}
}

void InputManager::deinit()
{
	if(!initialized())
		return;

	for(auto iter = mJoysticks.begin(); iter != mJoysticks.end(); iter++)
	{
		SDL_JoystickClose(iter->second);
	}
	mJoysticks.clear();

	for(auto iter = mInputConfigs.begin(); iter != mInputConfigs.end(); iter++)
	{
		delete iter->second;
	}
	mInputConfigs.clear();

	for(auto iter = mPrevAxisValues.begin(); iter != mPrevAxisValues.end(); iter++)
	{
		delete[] iter->second;
	}
	mPrevAxisValues.clear();

	if(mKeyboardInputConfig != NULL)
	{
		delete mKeyboardInputConfig;
		mKeyboardInputConfig = NULL;
	}

	SDL_JoystickEventState(SDL_DISABLE);
	SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
}

int InputManager::getNumJoysticks() { return mJoysticks.size(); }
int InputManager::getButtonCountByDevice(SDL_JoystickID id)
{
	if(id == DEVICE_KEYBOARD)
		return 120; //it's a lot, okay.
	else
		return SDL_JoystickNumButtons(mJoysticks[id]);
}

InputConfig* InputManager::getInputConfigByDevice(int device)
{
	if(device == DEVICE_KEYBOARD)
		return mKeyboardInputConfig;
	else
		return mInputConfigs[device];
}

bool InputManager::parseEvent(const SDL_Event& ev, Window* window)
{
	bool causedEvent = false;
	switch(ev.type)
	{
	case SDL_JOYAXISMOTION:
		//if it switched boundaries
		if((abs(ev.jaxis.value) > DEADZONE) != (abs(mPrevAxisValues[ev.jaxis.which][ev.jaxis.axis]) > DEADZONE))
		{
			int normValue;
			if(abs(ev.jaxis.value) <= DEADZONE)
				normValue = 0;
			else
				if(ev.jaxis.value > 0)
					normValue = 1;
				else
					normValue = -1;

			window->input(getInputConfigByDevice(ev.jaxis.which), Input(ev.jaxis.which, TYPE_AXIS, ev.jaxis.axis, normValue, false));
			causedEvent = true;
		}

		mPrevAxisValues[ev.jaxis.which][ev.jaxis.axis] = ev.jaxis.value;
		return causedEvent;

	case SDL_JOYBUTTONDOWN:
	case SDL_JOYBUTTONUP:
		window->input(getInputConfigByDevice(ev.jbutton.which), Input(ev.jbutton.which, TYPE_BUTTON, ev.jbutton.button, ev.jbutton.state == SDL_PRESSED, false));
		return true;

	case SDL_JOYHATMOTION:
		window->input(getInputConfigByDevice(ev.jhat.which), Input(ev.jhat.which, TYPE_HAT, ev.jhat.hat, ev.jhat.value, false));
		return true;

	case SDL_KEYDOWN:
		if(ev.key.keysym.sym == SDLK_BACKSPACE && SDL_IsTextInputActive())
		{
			window->textInput("\b");
		}

		if(ev.key.repeat)
			return false;

		if(ev.key.keysym.sym == SDLK_F4)
		{
			SDL_Event* quit = new SDL_Event();
			quit->type = SDL_QUIT;
			SDL_PushEvent(quit);
			return false;
		}

		window->input(getInputConfigByDevice(DEVICE_KEYBOARD), Input(DEVICE_KEYBOARD, TYPE_KEY, ev.key.keysym.sym, 1, false));
		return true;

	case SDL_KEYUP:
		window->input(getInputConfigByDevice(DEVICE_KEYBOARD), Input(DEVICE_KEYBOARD, TYPE_KEY, ev.key.keysym.sym, 0, false));
		return true;

	case SDL_TEXTINPUT:
		window->textInput(ev.text.text);
		break;

	case SDL_JOYDEVICEADDED:
		addJoystickByDeviceIndex(ev.jdevice.which); // ev.jdevice.which is a device index
		return true;

	case SDL_JOYDEVICEREMOVED:
		removeJoystickByJoystickID(ev.jdevice.which); // ev.jdevice.which is an SDL_JoystickID (instance ID)
		return false;
	}

	return false;
}

bool InputManager::loadInputConfig(InputConfig* config)
{
	std::string path = getConfigPath();
	if(!fs::exists(path))
		return false;

	pugi::xml_document doc;
	pugi::xml_parse_result res = doc.load_file(path.c_str());

	if(!res)
	{
		LOG(LogError) << "Error parsing input config: " << res.description();
		return false;
	}

	pugi::xml_node root = doc.child("inputList");
	if(!root)
		return false;

	pugi::xml_node configNode = root.find_child_by_attribute("inputConfig", "deviceGUID", config->getDeviceGUIDString().c_str());
	if(!configNode)
		configNode = root.find_child_by_attribute("inputConfig", "deviceName", config->getDeviceName().c_str());
	if(!configNode)
		return false;

	config->loadFromXML(configNode);
	return true;
}

//used in an "emergency" where no keyboard config could be loaded from the inputmanager config file
//allows the user to select to reconfigure in menus if this happens without having to delete es_input.cfg manually
void InputManager::loadDefaultKBConfig()
{
	InputConfig* cfg = getInputConfigByDevice(DEVICE_KEYBOARD);

	cfg->clear();
	cfg->mapInput("up", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_UP, 1, true));
	cfg->mapInput("down", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_DOWN, 1, true));
	cfg->mapInput("left", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_LEFT, 1, true));
	cfg->mapInput("right", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_RIGHT, 1, true));

	cfg->mapInput("a", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_RETURN, 1, true));
	cfg->mapInput("b", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_ESCAPE, 1, true));
	cfg->mapInput("start", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_F1, 1, true));
	cfg->mapInput("select", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_F2, 1, true));

	cfg->mapInput("pageup", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_RIGHTBRACKET, 1, true));
	cfg->mapInput("pagedown", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_LEFTBRACKET, 1, true));
}

void InputManager::writeDeviceConfig(InputConfig* config)
{
	assert(initialized());

	std::string path = getConfigPath();

	pugi::xml_document doc;

	if(fs::exists(path))
	{
		// merge files
		pugi::xml_parse_result result = doc.load_file(path.c_str());
		if(!result)
		{
			LOG(LogError) << "Error parsing input config: " << result.description();
		}else{
			// successfully loaded, delete the old entry if it exists
			pugi::xml_node root = doc.child("inputList");
			if(root)
			{
				pugi::xml_node oldEntry = root.find_child_by_attribute("inputConfig", "deviceGUID", config->getDeviceGUIDString().c_str());
				if(oldEntry)
					root.remove_child(oldEntry);
				oldEntry = root.find_child_by_attribute("inputConfig", "deviceName", config->getDeviceName().c_str());
				if(oldEntry)
					root.remove_child(oldEntry);
			}
		}
	}

	pugi::xml_node root = doc.child("inputList");
	if(!root)
		root = doc.append_child("inputList");

	config->writeToXML(root);
	doc.save_file(path.c_str());
}

std::string InputManager::getConfigPath()
{
	std::string path = getHomePath();
	path += "/.emulationstation/es_input.cfg";
	return path;
}

bool InputManager::initialized() const
{
	return mKeyboardInputConfig != NULL;
}

int InputManager::getNumConfiguredDevices()
{
	int num = 0;
	for(auto it = mInputConfigs.begin(); it != mInputConfigs.end(); it++)
	{
		if(it->second->isConfigured())
			num++;
	}

	if(mKeyboardInputConfig->isConfigured())
		num++;

	return num;
}

std::string InputManager::getDeviceGUIDString(int deviceId)
{
	if(deviceId == DEVICE_KEYBOARD)
		return KEYBOARD_GUID_STRING;

	auto it = mJoysticks.find(deviceId);
	if(it == mJoysticks.end())
	{
		LOG(LogError) << "getDeviceGUIDString - deviceId " << deviceId << " not found!";
		return "something went horribly wrong";
	}

	char guid[65];
	SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(it->second), guid, 65);
	return std::string(guid);
}
<commit_msg>Set hint regardless of setting (in case it is changed during run-time).<commit_after>#include "InputManager.h"
#include "InputConfig.h"
#include "Settings.h"
#include "Window.h"
#include "Log.h"
#include "pugixml/pugixml.hpp"
#include <boost/filesystem.hpp>
#include "platform.h"

#define KEYBOARD_GUID_STRING "-1"

// SO HEY POTENTIAL POOR SAP WHO IS TRYING TO MAKE SENSE OF ALL THIS (by which I mean my future self)
// There are like four distinct IDs used for joysticks (crazy, right?)
// 1. Device index - this is the "lowest level" identifier, and is just the Nth joystick plugged in to the system (like /dev/js#).
//    It can change even if the device is the same, and is only used to open joysticks (required to receive SDL events).
// 2. SDL_JoystickID - this is an ID for each joystick that is supposed to remain consistent between plugging and unplugging.
//    ES doesn't care if it does, though.
// 3. "Device ID" - this is something I made up and is what InputConfig's getDeviceID() returns.
//    This is actually just an SDL_JoystickID (also called instance ID), but -1 means "keyboard" instead of "error."
// 4. Joystick GUID - this is some squashed version of joystick vendor, version, and a bunch of other device-specific things.
//    It should remain the same across runs of the program/system restarts/device reordering and is what I use to identify which joystick to load.

namespace fs = boost::filesystem;

InputManager* InputManager::mInstance = NULL;

InputManager::InputManager() : mKeyboardInputConfig(NULL)
{
}

InputManager::~InputManager()
{
	deinit();
}

InputManager* InputManager::getInstance()
{
	if(!mInstance)
		mInstance = new InputManager();

	return mInstance;
}

void InputManager::init()
{
	if(initialized())
		deinit();

	SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,
		Settings::getInstance()->getBool("BackgroundJoystickInput") ? "1" : "0");
	SDL_InitSubSystem(SDL_INIT_JOYSTICK);
	SDL_JoystickEventState(SDL_ENABLE);

	// first, open all currently present joysticks
	int numJoysticks = SDL_NumJoysticks();
	for(int i = 0; i < numJoysticks; i++)
	{
		addJoystickByDeviceIndex(i);
	}

	mKeyboardInputConfig = new InputConfig(DEVICE_KEYBOARD, "Keyboard", KEYBOARD_GUID_STRING);
	loadInputConfig(mKeyboardInputConfig);
}

void InputManager::addJoystickByDeviceIndex(int id)
{
	assert(id >= 0 && id < SDL_NumJoysticks());

	// open joystick & add to our list
	SDL_Joystick* joy = SDL_JoystickOpen(id);
	assert(joy);

	// add it to our list so we can close it again later
	SDL_JoystickID joyId = SDL_JoystickInstanceID(joy);
	mJoysticks[joyId] = joy;

	char guid[65];
	SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joy), guid, 65);

	// create the InputConfig
	mInputConfigs[joyId] = new InputConfig(joyId, SDL_JoystickName(joy), guid);
	if(!loadInputConfig(mInputConfigs[joyId]))
	{
		LOG(LogInfo) << "Added unconfigured joystick " << SDL_JoystickName(joy) << " (GUID: " << guid << ", instance ID: " << joyId << ", device index: " << id << ").";
	}else{
		LOG(LogInfo) << "Added known joystick " << SDL_JoystickName(joy) << " (instance ID: " << joyId << ", device index: " << id << ")";
	}

	// set up the prevAxisValues
	int numAxes = SDL_JoystickNumAxes(joy);
	mPrevAxisValues[joyId] = new int[numAxes];
	std::fill(mPrevAxisValues[joyId], mPrevAxisValues[joyId] + numAxes, 0); //initialize array to 0
}

void InputManager::removeJoystickByJoystickID(SDL_JoystickID joyId)
{
	assert(joyId != -1);

	// delete old prevAxisValues
	auto axisIt = mPrevAxisValues.find(joyId);
	delete[] axisIt->second;
	mPrevAxisValues.erase(axisIt);

	// delete old InputConfig
	auto it = mInputConfigs.find(joyId);
	delete it->second;
	mInputConfigs.erase(it);

	// close the joystick
	auto joyIt = mJoysticks.find(joyId);
	if(joyIt != mJoysticks.end())
	{
		SDL_JoystickClose(joyIt->second);
		mJoysticks.erase(joyIt);
	}else{
		LOG(LogError) << "Could not find joystick to close (instance ID: " << joyId << ")";
	}
}

void InputManager::deinit()
{
	if(!initialized())
		return;

	for(auto iter = mJoysticks.begin(); iter != mJoysticks.end(); iter++)
	{
		SDL_JoystickClose(iter->second);
	}
	mJoysticks.clear();

	for(auto iter = mInputConfigs.begin(); iter != mInputConfigs.end(); iter++)
	{
		delete iter->second;
	}
	mInputConfigs.clear();

	for(auto iter = mPrevAxisValues.begin(); iter != mPrevAxisValues.end(); iter++)
	{
		delete[] iter->second;
	}
	mPrevAxisValues.clear();

	if(mKeyboardInputConfig != NULL)
	{
		delete mKeyboardInputConfig;
		mKeyboardInputConfig = NULL;
	}

	SDL_JoystickEventState(SDL_DISABLE);
	SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
}

int InputManager::getNumJoysticks() { return mJoysticks.size(); }
int InputManager::getButtonCountByDevice(SDL_JoystickID id)
{
	if(id == DEVICE_KEYBOARD)
		return 120; //it's a lot, okay.
	else
		return SDL_JoystickNumButtons(mJoysticks[id]);
}

InputConfig* InputManager::getInputConfigByDevice(int device)
{
	if(device == DEVICE_KEYBOARD)
		return mKeyboardInputConfig;
	else
		return mInputConfigs[device];
}

bool InputManager::parseEvent(const SDL_Event& ev, Window* window)
{
	bool causedEvent = false;
	switch(ev.type)
	{
	case SDL_JOYAXISMOTION:
		//if it switched boundaries
		if((abs(ev.jaxis.value) > DEADZONE) != (abs(mPrevAxisValues[ev.jaxis.which][ev.jaxis.axis]) > DEADZONE))
		{
			int normValue;
			if(abs(ev.jaxis.value) <= DEADZONE)
				normValue = 0;
			else
				if(ev.jaxis.value > 0)
					normValue = 1;
				else
					normValue = -1;

			window->input(getInputConfigByDevice(ev.jaxis.which), Input(ev.jaxis.which, TYPE_AXIS, ev.jaxis.axis, normValue, false));
			causedEvent = true;
		}

		mPrevAxisValues[ev.jaxis.which][ev.jaxis.axis] = ev.jaxis.value;
		return causedEvent;

	case SDL_JOYBUTTONDOWN:
	case SDL_JOYBUTTONUP:
		window->input(getInputConfigByDevice(ev.jbutton.which), Input(ev.jbutton.which, TYPE_BUTTON, ev.jbutton.button, ev.jbutton.state == SDL_PRESSED, false));
		return true;

	case SDL_JOYHATMOTION:
		window->input(getInputConfigByDevice(ev.jhat.which), Input(ev.jhat.which, TYPE_HAT, ev.jhat.hat, ev.jhat.value, false));
		return true;

	case SDL_KEYDOWN:
		if(ev.key.keysym.sym == SDLK_BACKSPACE && SDL_IsTextInputActive())
		{
			window->textInput("\b");
		}

		if(ev.key.repeat)
			return false;

		if(ev.key.keysym.sym == SDLK_F4)
		{
			SDL_Event* quit = new SDL_Event();
			quit->type = SDL_QUIT;
			SDL_PushEvent(quit);
			return false;
		}

		window->input(getInputConfigByDevice(DEVICE_KEYBOARD), Input(DEVICE_KEYBOARD, TYPE_KEY, ev.key.keysym.sym, 1, false));
		return true;

	case SDL_KEYUP:
		window->input(getInputConfigByDevice(DEVICE_KEYBOARD), Input(DEVICE_KEYBOARD, TYPE_KEY, ev.key.keysym.sym, 0, false));
		return true;

	case SDL_TEXTINPUT:
		window->textInput(ev.text.text);
		break;

	case SDL_JOYDEVICEADDED:
		addJoystickByDeviceIndex(ev.jdevice.which); // ev.jdevice.which is a device index
		return true;

	case SDL_JOYDEVICEREMOVED:
		removeJoystickByJoystickID(ev.jdevice.which); // ev.jdevice.which is an SDL_JoystickID (instance ID)
		return false;
	}

	return false;
}

bool InputManager::loadInputConfig(InputConfig* config)
{
	std::string path = getConfigPath();
	if(!fs::exists(path))
		return false;

	pugi::xml_document doc;
	pugi::xml_parse_result res = doc.load_file(path.c_str());

	if(!res)
	{
		LOG(LogError) << "Error parsing input config: " << res.description();
		return false;
	}

	pugi::xml_node root = doc.child("inputList");
	if(!root)
		return false;

	pugi::xml_node configNode = root.find_child_by_attribute("inputConfig", "deviceGUID", config->getDeviceGUIDString().c_str());
	if(!configNode)
		configNode = root.find_child_by_attribute("inputConfig", "deviceName", config->getDeviceName().c_str());
	if(!configNode)
		return false;

	config->loadFromXML(configNode);
	return true;
}

//used in an "emergency" where no keyboard config could be loaded from the inputmanager config file
//allows the user to select to reconfigure in menus if this happens without having to delete es_input.cfg manually
void InputManager::loadDefaultKBConfig()
{
	InputConfig* cfg = getInputConfigByDevice(DEVICE_KEYBOARD);

	cfg->clear();
	cfg->mapInput("up", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_UP, 1, true));
	cfg->mapInput("down", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_DOWN, 1, true));
	cfg->mapInput("left", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_LEFT, 1, true));
	cfg->mapInput("right", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_RIGHT, 1, true));

	cfg->mapInput("a", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_RETURN, 1, true));
	cfg->mapInput("b", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_ESCAPE, 1, true));
	cfg->mapInput("start", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_F1, 1, true));
	cfg->mapInput("select", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_F2, 1, true));

	cfg->mapInput("pageup", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_RIGHTBRACKET, 1, true));
	cfg->mapInput("pagedown", Input(DEVICE_KEYBOARD, TYPE_KEY, SDLK_LEFTBRACKET, 1, true));
}

void InputManager::writeDeviceConfig(InputConfig* config)
{
	assert(initialized());

	std::string path = getConfigPath();

	pugi::xml_document doc;

	if(fs::exists(path))
	{
		// merge files
		pugi::xml_parse_result result = doc.load_file(path.c_str());
		if(!result)
		{
			LOG(LogError) << "Error parsing input config: " << result.description();
		}else{
			// successfully loaded, delete the old entry if it exists
			pugi::xml_node root = doc.child("inputList");
			if(root)
			{
				pugi::xml_node oldEntry = root.find_child_by_attribute("inputConfig", "deviceGUID", config->getDeviceGUIDString().c_str());
				if(oldEntry)
					root.remove_child(oldEntry);
				oldEntry = root.find_child_by_attribute("inputConfig", "deviceName", config->getDeviceName().c_str());
				if(oldEntry)
					root.remove_child(oldEntry);
			}
		}
	}

	pugi::xml_node root = doc.child("inputList");
	if(!root)
		root = doc.append_child("inputList");

	config->writeToXML(root);
	doc.save_file(path.c_str());
}

std::string InputManager::getConfigPath()
{
	std::string path = getHomePath();
	path += "/.emulationstation/es_input.cfg";
	return path;
}

bool InputManager::initialized() const
{
	return mKeyboardInputConfig != NULL;
}

int InputManager::getNumConfiguredDevices()
{
	int num = 0;
	for(auto it = mInputConfigs.begin(); it != mInputConfigs.end(); it++)
	{
		if(it->second->isConfigured())
			num++;
	}

	if(mKeyboardInputConfig->isConfigured())
		num++;

	return num;
}

std::string InputManager::getDeviceGUIDString(int deviceId)
{
	if(deviceId == DEVICE_KEYBOARD)
		return KEYBOARD_GUID_STRING;

	auto it = mJoysticks.find(deviceId);
	if(it == mJoysticks.end())
	{
		LOG(LogError) << "getDeviceGUIDString - deviceId " << deviceId << " not found!";
		return "something went horribly wrong";
	}

	char guid[65];
	SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(it->second), guid, 65);
	return std::string(guid);
}
<|endoftext|>


<commit_before>/**
 * Clever programming language
 * Copyright (c) Clever Team
 *
 * This file is distributed under the MIT license. See LICENSE for details.
 */

#include "core/cstring.h"
#include "core/compiler.h"
#include "core/scope.h"
#include "core/value.h"
#include "core/location.hh"
#include "core/astdump.h"
#include "core/codegen.h"
#include "core/evaluator.h"
#include "core/resolver.h"

namespace clever {

/// Compiler initialization phase
void Compiler::init()
{
	m_pkg.init();
}

/// Frees all resource used by the compiler
void Compiler::shutdown()
{
	delete m_builder;

	m_pkg.shutdown();

	clever_delete_var(g_cstring_tbl);
}

/// Displays an error message and exits
void Compiler::error(const char* msg)
{
	std::cerr << "Compile error: " << msg << std::endl;
	CLEVER_EXIT_FATAL();
}

/// Displays an error message
void Compiler::error(const std::string& message, const location& loc)
{
	if (loc.begin.filename) {
		std::cerr << "Compile error: " << message << " on "
			<< *loc.begin.filename << " line " << loc.begin.line << "\n";
	} else {
		std::cerr << "Compile error: " << message << " on line "
			<< loc.begin.line << "\n";
	}
	CLEVER_EXIT_FATAL();
}

/// Displays a formatted error message and abort the compilation
void Compiler::errorf(const location& loc, const char* format, ...)
{
	std::ostringstream out;
	va_list args;

	va_start(args, format);

	vsprintf(out, format, args);

	va_end(args);

	error(out.str(), loc);
}

void Compiler::emitAST(ast::Node* tree)
{
	if (!tree) {
		return;
	}

	if (m_flags & USE_OPTIMIZER) {
		ast::Evaluator evaluator;
		tree = tree->accept(evaluator);
	}
	if (m_flags & DUMP_AST) {
		ast::Dumper astdump;
		tree->accept(astdump);
	}

	ast::Resolver resolver(m_pkg);
	tree->accept(resolver);

	if (!(m_flags & PARSER_ONLY)) {
		m_global_env = resolver.getGlobalEnv();

		m_builder = new IRBuilder(m_global_env);

		ast::Codegen codegen(this, m_builder);
		tree->accept(codegen);
	}

	clever_delete_var(tree);
}

} // clever
<commit_msg>- Added missing OP_HALT instruction<commit_after>/**
 * Clever programming language
 * Copyright (c) Clever Team
 *
 * This file is distributed under the MIT license. See LICENSE for details.
 */

#include "core/cstring.h"
#include "core/compiler.h"
#include "core/scope.h"
#include "core/value.h"
#include "core/location.hh"
#include "core/astdump.h"
#include "core/codegen.h"
#include "core/evaluator.h"
#include "core/resolver.h"

namespace clever {

/// Compiler initialization phase
void Compiler::init()
{
	m_pkg.init();
}

/// Frees all resource used by the compiler
void Compiler::shutdown()
{
	delete m_builder;

	m_pkg.shutdown();

	clever_delete_var(g_cstring_tbl);
}

/// Displays an error message and exits
void Compiler::error(const char* msg)
{
	std::cerr << "Compile error: " << msg << std::endl;
	CLEVER_EXIT_FATAL();
}

/// Displays an error message
void Compiler::error(const std::string& message, const location& loc)
{
	if (loc.begin.filename) {
		std::cerr << "Compile error: " << message << " on "
			<< *loc.begin.filename << " line " << loc.begin.line << "\n";
	} else {
		std::cerr << "Compile error: " << message << " on line "
			<< loc.begin.line << "\n";
	}
	CLEVER_EXIT_FATAL();
}

/// Displays a formatted error message and abort the compilation
void Compiler::errorf(const location& loc, const char* format, ...)
{
	std::ostringstream out;
	va_list args;

	va_start(args, format);

	vsprintf(out, format, args);

	va_end(args);

	error(out.str(), loc);
}

void Compiler::emitAST(ast::Node* tree)
{
	if (!tree) {
		return;
	}

	if (m_flags & USE_OPTIMIZER) {
		ast::Evaluator evaluator;
		tree = tree->accept(evaluator);
	}

	if (m_flags & DUMP_AST) {
		ast::Dumper astdump;
		tree->accept(astdump);
	}

	ast::Resolver resolver(m_pkg);
	tree->accept(resolver);

	if (!(m_flags & PARSER_ONLY)) {
		m_global_env = resolver.getGlobalEnv();

		m_builder = new IRBuilder(m_global_env);

		ast::Codegen codegen(this, m_builder);
		tree->accept(codegen);

		m_builder->push(OP_HALT);
	}

	clever_delete_var(tree);
}

} // clever
<|endoftext|>


<commit_before>#include <cassert>
#include "CodeGen_Bash.h"

using namespace Bish;

void CodeGen_Bash::indent() {
    for (unsigned i = 0; i < indent_level; i++) {
        stream << "    ";
    }
}

void CodeGen_Bash::visit(Module *n) {
    for (std::vector<Function *>::const_iterator I = n->functions.begin(),
             E = n->functions.end(); I != E; ++I) {
        (*I)->accept(this);
    }
    // Insert a call to bish_main().
    assert(n->main);
    FunctionCall *call_main = new FunctionCall(n->main);
    visit(call_main);
    stream << ";\n";
    delete call_main;
}

void CodeGen_Bash::visit(Block *n) {
    if (should_print_block_braces()) stream << "{\n";
    indent_level++;
    for (std::vector<IRNode *>::const_iterator I = n->nodes.begin(), E = n->nodes.end();
         I != E; ++I) {
        indent();
        (*I)->accept(this);
        stream << ";\n";
    }
    indent_level--;
    if (should_print_block_braces()) stream << "}\n\n";
}

void CodeGen_Bash::visit(Variable *n) {
    if (should_quote_variable()) stream << "\"";
    stream << "$" << lookup_name(n);
    if (should_quote_variable()) stream << "\"";
}

void CodeGen_Bash::visit(ReturnStatement *n) {
    stream << "echo ";
    enable_functioncall_wrap();
    n->value->accept(this);
    disable_functioncall_wrap();
    stream << "; exit";
}

void CodeGen_Bash::visit(IfStatement *n) {
    stream << "if [[ ";
    enable_functioncall_wrap();
    n->pblock->condition->accept(this);
    disable_functioncall_wrap();
    stream << " ]]; then\n";
    disable_block_braces();
    n->pblock->body->accept(this);

    for (std::vector<PredicatedBlock *>::const_iterator I = n->elses.begin(),
             E = n->elses.end(); I != E; ++I) {
        indent();
        stream << "elif [[ ";
        enable_functioncall_wrap();
        (*I)->condition->accept(this);
        disable_functioncall_wrap();
        stream << " ]]; then\n";
        (*I)->body->accept(this);
    }
    if (n->elseblock) {
        indent();
        stream << "else\n";
        n->elseblock->accept(this);
    }

    enable_block_braces();
    indent();
    stream << "fi";
}

void CodeGen_Bash::visit(ForLoop *n) {
    stream << "for " << lookup_name(n->variable) << " in ";
    if (n->upper) {
        stream << "$(seq ";
        n->lower->accept(this);
        stream << " ";
        n->upper->accept(this);
        stream << ")";
    } else {
        disable_quote_variable();
        n->lower->accept(this);
        enable_quote_variable();
    }
    stream << "; do\n";
    disable_block_braces();
    n->body->accept(this);
    enable_block_braces();
    indent();
    stream << "done";
}

void CodeGen_Bash::visit(Function *n) {
    stream << "function bish_" << n->name << " ";
    stream << "() ";
    LetScope *s = new LetScope();
    push_let_scope(s);
    // Bash doesn't allow named arguments to functions.
    // We have to translate to positional arguments.
    unsigned i = 1;
    for (std::vector<Variable *>::const_iterator I = n->args.begin(), E = n->args.end(); I != E; ++I, ++i) {
      s->add(*I, convert_string(i));
    }
    if (n->body) n->body->accept(this);
    pop_let_scope();
}

void CodeGen_Bash::visit(FunctionCall *n) {
    const int nargs = n->args.size();
    if (should_functioncall_wrap()) stream << "$(";
    stream << "bish_" << n->function->name;
    for (int i = 0; i < nargs; i++) {
        stream << " ";
        bool old = enable_functioncall_wrap();
        if (const FunctionCall *FC = dynamic_cast<const FunctionCall*>(n->args[i])) {
          if (should_quote_variable()) stream << "\"";
          n->args[i]->accept(this);
          if (should_quote_variable()) stream << "\"";
        } else {
          n->args[i]->accept(this);
        }
        set_functioncall_wrap(old);
    }
    if (should_functioncall_wrap()) stream << ")";
}

void CodeGen_Bash::visit(ExternCall *n) {
    if (should_functioncall_wrap()) stream << "$(";
    disable_quote_variable();
    for (InterpolatedString::const_iterator I = n->body->begin(), E = n->body->end();
         I != E; ++I) {
        if ((*I).is_str()) {
            stream << (*I).str();
        } else {
            assert((*I).is_var());
            visit((*I).var());
        }
    }
    enable_quote_variable();
    if (should_functioncall_wrap()) stream << ")";
}

void CodeGen_Bash::visit(Assignment *n) {
    stream << lookup_name(n->variable) << "=";
    enable_functioncall_wrap();
    n->value->accept(this);
    disable_functioncall_wrap();
}

void CodeGen_Bash::visit(BinOp *n) {
    std::string bash_op;
    bool comparison = false;
    switch (n->op) {
    case BinOp::Eq:
        bash_op = n->type() == StringTy ? "==" : "-eq";
        comparison = true;
        break;
    case BinOp::NotEq:
        bash_op = n->type() == StringTy ? "!=" : "-ne";
        comparison = true;
        break;
    case BinOp::LT:
        bash_op = "<";
        comparison = true;
        break;
    case BinOp::LTE:
        bash_op = "<=";
        comparison = true;
        break;
    case BinOp::GT:
        bash_op = ">";
        comparison = true;
        break;
    case BinOp::GTE:
        bash_op = ">=";
        comparison = true;
        break;
    case BinOp::Add:
        bash_op = "+";
        break;
    case BinOp::Sub:
        bash_op = "-";
        break;
    case BinOp::Mul:
        bash_op = "*";
        break;
    case BinOp::Div:
        bash_op = "/";
        break;
    case BinOp::Mod:
        bash_op = "%";
        break;
    }

    if (!comparison) stream << "$((";
    disable_quote_variable();
    n->a->accept(this);
    stream << " " << bash_op << " ";
    n->b->accept(this);
    if (!comparison) stream << "))";
    enable_quote_variable();
}

void CodeGen_Bash::visit(UnaryOp *n) {
    switch (n->op) {
    case UnaryOp::Negate:
        stream << "-";
        break;
    }
    n->a->accept(this);
}

void CodeGen_Bash::visit(Integer *n) {
    stream << n->value;
}

void CodeGen_Bash::visit(Fractional *n) {
    stream << n->value;
}

void CodeGen_Bash::visit(String *n) {
    stream << "\"" << n->value << "\"";
}

void CodeGen_Bash::visit(Boolean *n) {
    stream << n->value;
}
<commit_msg>Fix non-binary operators in conditionals.<commit_after>#include <cassert>
#include "CodeGen_Bash.h"

using namespace Bish;

void CodeGen_Bash::indent() {
    for (unsigned i = 0; i < indent_level; i++) {
        stream << "    ";
    }
}

void CodeGen_Bash::visit(Module *n) {
    for (std::vector<Function *>::const_iterator I = n->functions.begin(),
             E = n->functions.end(); I != E; ++I) {
        (*I)->accept(this);
    }
    // Insert a call to bish_main().
    assert(n->main);
    FunctionCall *call_main = new FunctionCall(n->main);
    visit(call_main);
    stream << ";\n";
    delete call_main;
}

void CodeGen_Bash::visit(Block *n) {
    if (should_print_block_braces()) stream << "{\n";
    indent_level++;
    for (std::vector<IRNode *>::const_iterator I = n->nodes.begin(), E = n->nodes.end();
         I != E; ++I) {
        indent();
        (*I)->accept(this);
        stream << ";\n";
    }
    indent_level--;
    if (should_print_block_braces()) stream << "}\n\n";
}

void CodeGen_Bash::visit(Variable *n) {
    if (should_quote_variable()) stream << "\"";
    stream << "$" << lookup_name(n);
    if (should_quote_variable()) stream << "\"";
}

void CodeGen_Bash::visit(ReturnStatement *n) {
    stream << "echo ";
    enable_functioncall_wrap();
    n->value->accept(this);
    disable_functioncall_wrap();
    stream << "; exit";
}

void CodeGen_Bash::visit(IfStatement *n) {
    stream << "if [[ ";
    enable_functioncall_wrap();
    n->pblock->condition->accept(this);
    if (dynamic_cast<BinOp*>(n->pblock->condition) == NULL) {
        stream << " -eq 1";
    }
    disable_functioncall_wrap();
    stream << " ]]; then\n";
    disable_block_braces();
    n->pblock->body->accept(this);

    for (std::vector<PredicatedBlock *>::const_iterator I = n->elses.begin(),
             E = n->elses.end(); I != E; ++I) {
        indent();
        stream << "elif [[ ";
        enable_functioncall_wrap();
        (*I)->condition->accept(this);
        disable_functioncall_wrap();
        stream << " ]]; then\n";
        (*I)->body->accept(this);
    }
    if (n->elseblock) {
        indent();
        stream << "else\n";
        n->elseblock->accept(this);
    }

    enable_block_braces();
    indent();
    stream << "fi";
}

void CodeGen_Bash::visit(ForLoop *n) {
    stream << "for " << lookup_name(n->variable) << " in ";
    if (n->upper) {
        stream << "$(seq ";
        n->lower->accept(this);
        stream << " ";
        n->upper->accept(this);
        stream << ")";
    } else {
        disable_quote_variable();
        n->lower->accept(this);
        enable_quote_variable();
    }
    stream << "; do\n";
    disable_block_braces();
    n->body->accept(this);
    enable_block_braces();
    indent();
    stream << "done";
}

void CodeGen_Bash::visit(Function *n) {
    stream << "function bish_" << n->name << " ";
    stream << "() ";
    LetScope *s = new LetScope();
    push_let_scope(s);
    // Bash doesn't allow named arguments to functions.
    // We have to translate to positional arguments.
    unsigned i = 1;
    for (std::vector<Variable *>::const_iterator I = n->args.begin(), E = n->args.end(); I != E; ++I, ++i) {
      s->add(*I, convert_string(i));
    }
    if (n->body) n->body->accept(this);
    pop_let_scope();
}

void CodeGen_Bash::visit(FunctionCall *n) {
    const int nargs = n->args.size();
    if (should_functioncall_wrap()) stream << "$(";
    stream << "bish_" << n->function->name;
    for (int i = 0; i < nargs; i++) {
        stream << " ";
        bool old = enable_functioncall_wrap();
        if (const FunctionCall *FC = dynamic_cast<const FunctionCall*>(n->args[i])) {
          if (should_quote_variable()) stream << "\"";
          n->args[i]->accept(this);
          if (should_quote_variable()) stream << "\"";
        } else {
          n->args[i]->accept(this);
        }
        set_functioncall_wrap(old);
    }
    if (should_functioncall_wrap()) stream << ")";
}

void CodeGen_Bash::visit(ExternCall *n) {
    if (should_functioncall_wrap()) stream << "$(";
    disable_quote_variable();
    for (InterpolatedString::const_iterator I = n->body->begin(), E = n->body->end();
         I != E; ++I) {
        if ((*I).is_str()) {
            stream << (*I).str();
        } else {
            assert((*I).is_var());
            visit((*I).var());
        }
    }
    enable_quote_variable();
    if (should_functioncall_wrap()) stream << ")";
}

void CodeGen_Bash::visit(Assignment *n) {
    stream << lookup_name(n->variable) << "=";
    enable_functioncall_wrap();
    n->value->accept(this);
    disable_functioncall_wrap();
}

void CodeGen_Bash::visit(BinOp *n) {
    std::string bash_op;
    bool comparison = false;
    switch (n->op) {
    case BinOp::Eq:
        bash_op = n->type() == StringTy ? "==" : "-eq";
        comparison = true;
        break;
    case BinOp::NotEq:
        bash_op = n->type() == StringTy ? "!=" : "-ne";
        comparison = true;
        break;
    case BinOp::LT:
        bash_op = "<";
        comparison = true;
        break;
    case BinOp::LTE:
        bash_op = "<=";
        comparison = true;
        break;
    case BinOp::GT:
        bash_op = ">";
        comparison = true;
        break;
    case BinOp::GTE:
        bash_op = ">=";
        comparison = true;
        break;
    case BinOp::Add:
        bash_op = "+";
        break;
    case BinOp::Sub:
        bash_op = "-";
        break;
    case BinOp::Mul:
        bash_op = "*";
        break;
    case BinOp::Div:
        bash_op = "/";
        break;
    case BinOp::Mod:
        bash_op = "%";
        break;
    }

    if (!comparison) stream << "$((";
    disable_quote_variable();
    n->a->accept(this);
    stream << " " << bash_op << " ";
    n->b->accept(this);
    if (!comparison) stream << "))";
    enable_quote_variable();
}

void CodeGen_Bash::visit(UnaryOp *n) {
    switch (n->op) {
    case UnaryOp::Negate:
        stream << "-";
        break;
    }
    n->a->accept(this);
}

void CodeGen_Bash::visit(Integer *n) {
    stream << n->value;
}

void CodeGen_Bash::visit(Fractional *n) {
    stream << n->value;
}

void CodeGen_Bash::visit(String *n) {
    stream << "\"" << n->value << "\"";
}

void CodeGen_Bash::visit(Boolean *n) {
    stream << n->value;
}
<|endoftext|>


<commit_before>#include "CodeGenerator.hpp"
#include "AST.hpp"

GenericValue CodeGenerator::runCode()
{
    std::cout<<"Now.. Running Code"<<std::endl;
    ExistingModuleProvider *EMP = new ExistingModuleProvider(module);
    ExectionEngine *EE = ExectuionEngine::create(EMP, false);
    std::vector <GenericValue> gv_vec;

    GenericValue gv = EE->runFunction(mainFunc, gv_vec);

    return gv;

}

CodeBlock*  CodeGenerator::popStack()
{
  CodeBlock* value = null;
  if(!this.block_stack.empty())
  {

     value = this.block_stack.pop();
  }

  return value;

}

void CodeGenerator::pushStack(CodeBlock *block)
{
    this.block_stack.push(block);
}

void CodeGenerator::GenerateCode()
{
     std::cout<<"Now Generatring Code...."<<std::endl;

     FunctionType *ftype = FuntionType::get(Type::getInt32Ty
     this._mainFunc = llvm::Function::Create(this._globalContext, "main", this._module);
     BasicBlock *BB = BasicBlock::Create(this._globalContext, "EntryBlock", this._mainFunc);

}
<commit_msg>2014-10-18<commit_after>#include "CodeGenerator.hpp"
#include "AST.hpp"

GenericValue CodeGenerator::runCode()
{
    std::cout<<"Now.. Running Code"<<std::endl;
    ExistingModuleProvider *EMP = new ExistingModuleProvider(module);
    ExectionEngine *EE = ExectuionEngine::create(EMP, false);
    std::vector <GenericValue> gv_vec;

    GenericValue gv = EE->runFunction(this._mainFunc, gv_vec);

    return gv;

}

CodeBlock*  CodeGenerator::popStack()
{
  CodeBlock* value = null;
  if(!this.block_stack.empty())
  {

     value = this.block_stack.pop();
  }

  return value;

}

void CodeGenerator::pushStack(CodeBlock *block)
{
    this.block_stack.push(block);
}

void CodeGenerator::GenerateCode()
{
     std::cout<<"Now Generatring Code...."<<std::endl;

     FunctionType *ftype = FuntionType::get(Type::getInt32Ty
     this._mainFunc = llvm::Function::Create(this._globalContext, "main", this._module);
     BasicBlock *BB = BasicBlock::Create(this._globalContext, "EntryBlock", this._mainFunc);

}
<|endoftext|>


<commit_before>// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/vespalib/util/exception.h>
#include <vespa/vespalib/util/slaveproc.h>

using namespace vespalib;

TEST("that uncaught exception causes negative exitcode.") {
    SlaveProc proc("ulimit -c 0 && exec ./vespalib_caught_uncaught_app uncaught");
    proc.wait();
    EXPECT_LESS(proc.getExitCode(), 0);
}

TEST("that uncaught silenced exception causes exitcode 66") {
    SlaveProc proc("ulimit -c 0 && exec ./vespalib_caught_uncaught_app silenced_and_uncaught");
    proc.wait();
    EXPECT_EQUAL(proc.getExitCode(), 66);
}

TEST("that caught silenced exception followed by an uncaught causes negative exitcode.") {
    SlaveProc proc("ulimit -c 0 && exec ./vespalib_caught_uncaught_app uncaught_after_silenced_and_caught");
    proc.wait();
    EXPECT_LESS(proc.getExitCode(), 0);
}

TEST("that caught silenced exception causes exitcode 0") {
    SlaveProc proc("ulimit -c 0 && exec ./vespalib_caught_uncaught_app silenced_and_caught");
    proc.wait();
    EXPECT_EQUAL(proc.getExitCode(), 0);
}

TEST("that mmap within limits are fine cause exitcode 0") {
    SlaveProc proc("ulimit -c 0 && exec ./vespalib_mmap_app 100000000 10485760 1");
    proc.wait();
    EXPECT_EQUAL(proc.getExitCode(), 0);
}

TEST("that mmap beyond limits cause negative exitcode.") {
    SlaveProc proc("ulimit -c 0 && exec ./vespalib_mmap_app 100000000 10485760 10");
    proc.wait();
    EXPECT_LESS(proc.getExitCode(), 0);
}

TEST("that mmap beyond limits with set VESPA_SILENCE_CORE_ON_OOM cause exitcode 66.") {
    SlaveProc proc("ulimit -c 0 && VESPA_SILENCE_CORE_ON_OOM=1 exec ./vespalib_mmap_app 100000000 10485760 10");
    proc.wait();
    EXPECT_EQUAL(proc.getExitCode(), 66);
}

TEST_MAIN_WITH_PROCESS_PROXY() { TEST_RUN_ALL(); }
<commit_msg>ulimit -c 0 only when needed<commit_after>// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/vespalib/util/exception.h>
#include <vespa/vespalib/util/slaveproc.h>

using namespace vespalib;

TEST("that uncaught exception causes negative exitcode.") {
    SlaveProc proc("ulimit -c 0 && exec ./vespalib_caught_uncaught_app uncaught");
    proc.wait();
    EXPECT_LESS(proc.getExitCode(), 0);
}

TEST("that uncaught silenced exception causes exitcode 66") {
    SlaveProc proc("exec ./vespalib_caught_uncaught_app silenced_and_uncaught");
    proc.wait();
    EXPECT_EQUAL(proc.getExitCode(), 66);
}

TEST("that caught silenced exception followed by an uncaught causes negative exitcode.") {
    SlaveProc proc("ulimit -c 0 && exec ./vespalib_caught_uncaught_app uncaught_after_silenced_and_caught");
    proc.wait();
    EXPECT_LESS(proc.getExitCode(), 0);
}

TEST("that caught silenced exception causes exitcode 0") {
    SlaveProc proc("exec ./vespalib_caught_uncaught_app silenced_and_caught");
    proc.wait();
    EXPECT_EQUAL(proc.getExitCode(), 0);
}

TEST("that mmap within limits are fine cause exitcode 0") {
    SlaveProc proc("exec ./vespalib_mmap_app 100000000 10485760 1");
    proc.wait();
    EXPECT_EQUAL(proc.getExitCode(), 0);
}

TEST("that mmap beyond limits cause negative exitcode.") {
    SlaveProc proc("ulimit -c 0 && exec ./vespalib_mmap_app 100000000 10485760 10");
    proc.wait();
    EXPECT_LESS(proc.getExitCode(), 0);
}

TEST("that mmap beyond limits with set VESPA_SILENCE_CORE_ON_OOM cause exitcode 66.") {
    SlaveProc proc("VESPA_SILENCE_CORE_ON_OOM=1 exec ./vespalib_mmap_app 100000000 10485760 10");
    proc.wait();
    EXPECT_EQUAL(proc.getExitCode(), 66);
}

TEST_MAIN_WITH_PROCESS_PROXY() { TEST_RUN_ALL(); }
<|endoftext|>


<commit_before>/*!
 * \file Utils.cpp
 * \brief Utility functions - implementation
 * \author mstefanc
 * \date Jun 9, 2010
 */

#include "Utils.hpp"

#include <string>
#include <vector>

#define BOOST_FILESYSTEM_VERSION 2
#include <boost/filesystem.hpp>
using namespace boost::filesystem;

#include <boost/regex.hpp>
#include <boost/foreach.hpp>

using namespace std;

namespace Utils {

std::vector<std::string> searchFiles(const std::string & root, const std::string & regexp, bool with_path) {
	boost::regex e(regexp);
	std::vector<std::string> ret;

	path dir_path(root);
	if ( !exists( dir_path ) )
		return ret;

	directory_iterator end_itr; // default construction yields past-the-end
	for ( directory_iterator itr( dir_path ); itr != end_itr; ++itr )
	{
		std::string fname = itr->path().filename();
		if (regex_match(fname, e)) {
			if (with_path)
				ret.push_back(itr->path().file_string());
			else
				ret.push_back(fname);
		}
	}

	return ret;
}

std::vector<std::string> getSubdirs(const std::string & root, bool with_path) {
	std::vector<std::string> ret;

	path dir_path(root);
	if ( !exists( dir_path ) )
		return ret;

	directory_iterator end_itr; // default construction yields past-the-end
	for ( directory_iterator itr( dir_path ); itr != end_itr; ++itr )
	{
		std::string fname = itr->path().filename();
		if (is_directory(itr->status())) {
			if (with_path)
				ret.push_back(itr->path().file_string());
			else
				ret.push_back(fname);
		}
	}

	return ret;
}

std::string findSubdir(const std::string & name, const std::vector<std::string> & roots, bool with_path) {
	std::string root;
	BOOST_FOREACH(root, roots) {
		path dir_path(root);
		if ( !exists( dir_path ) )
			continue;

		directory_iterator end_itr; // default construction yields past-the-end
		for ( directory_iterator itr( dir_path ); itr != end_itr; ++itr )
		{
			std::string fname = itr->path().filename();
			if (is_directory(itr->status()) && fname == name) {
				if (with_path)
					return itr->path().file_string();
				else
					return fname;
			}
		}
	}

	return "";
}

} //: namespace Utils
<commit_msg>Last Filesystem V3 fix<commit_after>/*!
 * \file Utils.cpp
 * \brief Utility functions - implementation
 * \author mstefanc
 * \date Jun 9, 2010
 */

#include "Utils.hpp"

#include <string>
#include <vector>

#include <boost/filesystem.hpp>
using namespace boost::filesystem;

#include <boost/regex.hpp>
#include <boost/foreach.hpp>

using namespace std;

namespace Utils {

std::vector<std::string> searchFiles(const std::string & root, const std::string & regexp, bool with_path) {
	boost::regex e(regexp);
	std::vector<std::string> ret;

	path dir_path(root);
	if ( !exists( dir_path ) )
		return ret;

	directory_iterator end_itr; // default construction yields past-the-end
	for ( directory_iterator itr( dir_path ); itr != end_itr; ++itr )
	{
		std::string fname = itr->path().filename().string();
		if (regex_match(fname, e)) {
			if (with_path)
				ret.push_back(itr->path().string());
			else
				ret.push_back(fname);
		}
	}

	return ret;
}

std::vector<std::string> getSubdirs(const std::string & root, bool with_path) {
	std::vector<std::string> ret;

	path dir_path(root);
	if ( !exists( dir_path ) )
		return ret;

	directory_iterator end_itr; // default construction yields past-the-end
	for ( directory_iterator itr( dir_path ); itr != end_itr; ++itr )
	{
		std::string fname = itr->path().filename().string();
		if (is_directory(itr->status())) {
			if (with_path)
				ret.push_back(itr->path().string());
			else
				ret.push_back(fname);
		}
	}

	return ret;
}

std::string findSubdir(const std::string & name, const std::vector<std::string> & roots, bool with_path) {
	std::string root;
	BOOST_FOREACH(root, roots) {
		path dir_path(root);
		if ( !exists( dir_path ) )
			continue;

		directory_iterator end_itr; // default construction yields past-the-end
		for ( directory_iterator itr( dir_path ); itr != end_itr; ++itr )
		{
			std::string fname = itr->path().filename().string();
			if (is_directory(itr->status()) && fname == name) {
				if (with_path)
					return itr->path().string();
				else
					return fname;
			}
		}
	}

	return "";
}

} //: namespace Utils
<|endoftext|>


<commit_before>
#include "queued_cpu_tracker.h"
#ifdef WIN32
#include <Windows.h>
#undef AddJob
#endif

static int PDT_BytesPerPixel(QTRK_PixelDataType pdt) {
	const int pdtBytes[] = {1, 2, 4};
	return pdtBytes[(int)pdt];
}

void QueuedCPUTracker::JobFinished(QueuedCPUTracker::Job* j)
{
	pthread_mutex_lock(&jobs_buffer_mutex);
	jobs_buffer.push_back(j);
	pthread_mutex_unlock(&jobs_buffer_mutex);
}

QueuedCPUTracker::Job* QueuedCPUTracker::GetNextJob()
{
	QueuedCPUTracker::Job *j = 0;
	pthread_mutex_lock(&jobs_mutex);
	if (!jobs.empty()) {
		j = jobs.front();
		jobs.pop_front();
	}
	pthread_mutex_unlock(&jobs_mutex);
	return j;
}

QueuedCPUTracker::Job* QueuedCPUTracker::AllocateJob()
{
	QueuedCPUTracker::Job *j;
	pthread_mutex_lock(&jobs_buffer_mutex);
	if (!jobs_buffer.empty()) {
		j = jobs_buffer.back();
		jobs_buffer.pop_back();
	} else
		j = new Job;
	pthread_mutex_unlock(&jobs_buffer_mutex);
	return j;
}

void QueuedCPUTracker::AddJob(Job* j)
{
	pthread_mutex_lock(&jobs_mutex);
	jobs.push_back(j);
	pthread_mutex_unlock(&jobs_mutex);
}

QueuedCPUTracker::QueuedCPUTracker(int w, int h, int xcorw, int numThreads)
{
	quitWork = false;
	threads.resize(numThreads);
	for (int k=0;k<numThreads;k++) {
		threads[k].tracker = new CPUTracker(w, h, xcorw);
		threads[k].manager = this;
	}

	pthread_attr_init(&joinable_attr);
	pthread_attr_setdetachstate(&joinable_attr, PTHREAD_CREATE_JOINABLE);

	pthread_mutex_init(&jobs_mutex,0);
	pthread_mutex_init(&results_mutex,0);
	pthread_mutex_init(&jobs_buffer_mutex,0);
}

QueuedCPUTracker::~QueuedCPUTracker()
{
	// wait for threads to finish
	quitWork = true;

	for (int k=0;k<threads.size();k++) {
		pthread_join(threads[k].thread, 0);
		delete threads[k].tracker;
	}
	pthread_attr_destroy(&joinable_attr);
	pthread_mutex_destroy(&jobs_mutex);
	pthread_mutex_destroy(&jobs_buffer_mutex);
	pthread_mutex_destroy(&results_mutex);

	// free job memory
	DeleteAllElems(jobs);
	DeleteAllElems(jobs_buffer);
}

void QueuedCPUTracker::Start()
{
	quitWork = false;

	for (int k=0;k<threads.size();k++) {
		pthread_create(&threads[k].thread, &joinable_attr, WorkerThreadMain, (void*)&threads[k]);
	}
}

void* QueuedCPUTracker::WorkerThreadMain(void* arg)
{
	Thread* th = (Thread*)arg;
	QueuedCPUTracker* this_ = th->manager;

	while (!this_->quitWork) {

		Job* j = this_->GetNextJob();
		if (j) {
			this_->ProcessJob(th, j);
		} else {
			#ifdef WIN32
				Sleep(1);
			#endif
		}
	}
	return 0;
}

void QueuedCPUTracker::ProcessJob(Thread* th, Job* j)
{
	if (j->dataType == QTrkU8) {
		th->tracker->SetImage8Bit(j->data, width);
	} else if (j->dataType == QTrkU16) {
		th->tracker->SetImage16Bit((ushort*)j->data, width*2);
	} else {
		th->tracker->SetImageFloat((float*)j->data);
	}

	LocalizationResult result={};
	result.id = j->id;
	result.locType = j->locType;
	result.zlutIndex = j->zlut;

	vector2f com = th->tracker->ComputeBgCorrectedCOM();
	if (j->locType == LocalizeXCor1D) {
		result.firstGuess = com;
		result.pos = th->tracker->ComputeXCorInterpolated(com, cfg.xcor1D_iterations, cfg.profileWidth);
	} else if(j->locType == LocalizeOnlyCOM) {
		result.firstGuess = result.pos = com;
	} else if(j->locType == LocalizeQI) {
		result.firstGuess = com;
		result.pos = th->tracker->ComputeQI(com, cfg.qi_iterations, cfg.qi_radialsteps, cfg.qi_angularsteps, cfg.qi_maxr);
	}

	pthread_mutex_lock(&results_mutex);
	results.push_back(result);
	pthread_mutex_unlock(&results_mutex);
}

void QueuedCPUTracker::SetZLUT(float* data, int planes, int res, int num_zluts, float prof_radius, int angularSteps)
{
}

void QueuedCPUTracker::ComputeRadialProfile(float* dst, int radialSteps, int angularSteps, float radius, vector2f center)
{
}

void QueuedCPUTracker::ScheduleLocalization(uchar* data, int pitch, QTRK_PixelDataType pdt,
				Localize2DType locType, bool computeZ, uint id, uint zlutIndex)
{
	Job* j = AllocateJob();
	int dstPitch = PDT_BytesPerPixel(pdt) * width;

	if(!j->data || j->dataType != pdt) {
		if (j->data) delete[] j->data;
		j->data = new uchar[dstPitch * height];
	}
	for (int y=0;y<height;y++)
		memcpy(&j->data[dstPitch*y], &data[pitch*y], dstPitch);

	j->dataType = pdt;
	j->id = id;
	j->locType = locType;
	j->zlut = zlutIndex;

	AddJob(j);
}

int QueuedCPUTracker::PollFinished(LocalizationResult* dstResults, int maxResults)
{
	int numResults = 0;
	pthread_mutex_lock(&results_mutex);
	while (numResults < maxResults && !results.empty()) {
		dstResults[numResults++] = results.front();
		results.pop_front();
	}
	pthread_mutex_unlock(&results_mutex);
	return numResults;
}

<commit_msg>call JobFinished()<commit_after>
#include "queued_cpu_tracker.h"
#ifdef WIN32
#include <Windows.h>
#undef AddJob
#endif

static int PDT_BytesPerPixel(QTRK_PixelDataType pdt) {
	const int pdtBytes[] = {1, 2, 4};
	return pdtBytes[(int)pdt];
}

void QueuedCPUTracker::JobFinished(QueuedCPUTracker::Job* j)
{
	pthread_mutex_lock(&jobs_buffer_mutex);
	jobs_buffer.push_back(j);
	pthread_mutex_unlock(&jobs_buffer_mutex);
}

QueuedCPUTracker::Job* QueuedCPUTracker::GetNextJob()
{
	QueuedCPUTracker::Job *j = 0;
	pthread_mutex_lock(&jobs_mutex);
	if (!jobs.empty()) {
		j = jobs.front();
		jobs.pop_front();
	}
	pthread_mutex_unlock(&jobs_mutex);
	return j;
}

QueuedCPUTracker::Job* QueuedCPUTracker::AllocateJob()
{
	QueuedCPUTracker::Job *j;
	pthread_mutex_lock(&jobs_buffer_mutex);
	if (!jobs_buffer.empty()) {
		j = jobs_buffer.back();
		jobs_buffer.pop_back();
	} else
		j = new Job;
	pthread_mutex_unlock(&jobs_buffer_mutex);
	return j;
}

void QueuedCPUTracker::AddJob(Job* j)
{
	pthread_mutex_lock(&jobs_mutex);
	jobs.push_back(j);
	pthread_mutex_unlock(&jobs_mutex);
}

QueuedCPUTracker::QueuedCPUTracker(int w, int h, int xcorw, int numThreads)
{
	quitWork = false;
	threads.resize(numThreads);
	for (int k=0;k<numThreads;k++) {
		threads[k].tracker = new CPUTracker(w, h, xcorw);
		threads[k].manager = this;
	}

	pthread_attr_init(&joinable_attr);
	pthread_attr_setdetachstate(&joinable_attr, PTHREAD_CREATE_JOINABLE);

	pthread_mutex_init(&jobs_mutex,0);
	pthread_mutex_init(&results_mutex,0);
	pthread_mutex_init(&jobs_buffer_mutex,0);
}

QueuedCPUTracker::~QueuedCPUTracker()
{
	// wait for threads to finish
	quitWork = true;

	for (int k=0;k<threads.size();k++) {
		pthread_join(threads[k].thread, 0);
		delete threads[k].tracker;
	}
	pthread_attr_destroy(&joinable_attr);
	pthread_mutex_destroy(&jobs_mutex);
	pthread_mutex_destroy(&jobs_buffer_mutex);
	pthread_mutex_destroy(&results_mutex);

	// free job memory
	DeleteAllElems(jobs);
	DeleteAllElems(jobs_buffer);
}

void QueuedCPUTracker::Start()
{
	quitWork = false;

	for (int k=0;k<threads.size();k++) {
		pthread_create(&threads[k].thread, &joinable_attr, WorkerThreadMain, (void*)&threads[k]);
	}
}

void* QueuedCPUTracker::WorkerThreadMain(void* arg)
{
	Thread* th = (Thread*)arg;
	QueuedCPUTracker* this_ = th->manager;

	while (!this_->quitWork) {

		Job* j = this_->GetNextJob();
		if (j) {
			this_->ProcessJob(th, j);
			this_->JobFinished(j);
		} else {
			#ifdef WIN32
				Sleep(1);
			#endif
		}
	}
	return 0;
}

void QueuedCPUTracker::ProcessJob(Thread* th, Job* j)
{
	if (j->dataType == QTrkU8) {
		th->tracker->SetImage8Bit(j->data, width);
	} else if (j->dataType == QTrkU16) {
		th->tracker->SetImage16Bit((ushort*)j->data, width*2);
	} else {
		th->tracker->SetImageFloat((float*)j->data);
	}

	LocalizationResult result={};
	result.id = j->id;
	result.locType = j->locType;
	result.zlutIndex = j->zlut;

	vector2f com = th->tracker->ComputeBgCorrectedCOM();
	if (j->locType == LocalizeXCor1D) {
		result.firstGuess = com;
		result.pos = th->tracker->ComputeXCorInterpolated(com, cfg.xcor1D_iterations, cfg.profileWidth);
	} else if(j->locType == LocalizeOnlyCOM) {
		result.firstGuess = result.pos = com;
	} else if(j->locType == LocalizeQI) {
		result.firstGuess = com;
		result.pos = th->tracker->ComputeQI(com, cfg.qi_iterations, cfg.qi_radialsteps, cfg.qi_angularsteps, cfg.qi_maxr);
	}

	pthread_mutex_lock(&results_mutex);
	results.push_back(result);
	pthread_mutex_unlock(&results_mutex);
}

void QueuedCPUTracker::SetZLUT(float* data, int planes, int res, int num_zluts, float prof_radius, int angularSteps)
{
}

void QueuedCPUTracker::ComputeRadialProfile(float* dst, int radialSteps, int angularSteps, float radius, vector2f center)
{
}

void QueuedCPUTracker::ScheduleLocalization(uchar* data, int pitch, QTRK_PixelDataType pdt,
				Localize2DType locType, bool computeZ, uint id, uint zlutIndex)
{
	Job* j = AllocateJob();
	int dstPitch = PDT_BytesPerPixel(pdt) * width;

	if(!j->data || j->dataType != pdt) {
		if (j->data) delete[] j->data;
		j->data = new uchar[dstPitch * height];
	}
	for (int y=0;y<height;y++)
		memcpy(&j->data[dstPitch*y], &data[pitch*y], dstPitch);

	j->dataType = pdt;
	j->id = id;
	j->locType = locType;
	j->zlut = zlutIndex;

	AddJob(j);
}

int QueuedCPUTracker::PollFinished(LocalizationResult* dstResults, int maxResults)
{
	int numResults = 0;
	pthread_mutex_lock(&results_mutex);
	while (numResults < maxResults && !results.empty()) {
		dstResults[numResults++] = results.front();
		results.pop_front();
	}
	pthread_mutex_unlock(&results_mutex);
	return numResults;
}

<|endoftext|>


<commit_before>/*-----------------------------------------------------------------------------------------------
The MIT License (MIT)

Copyright (c) 2014-2016 Kim Kulling

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-----------------------------------------------------------------------------------------------*/
#include <cppcore/Random/RandomGenerator.h>

#include <stdlib.h>
#include <time.h>
#include <cassert>

namespace CPPCore {

static const unsigned int N = 624;
static const unsigned int M = 397;

static void mersenne_twister_vector_init( unsigned int *seedPoints, size_t len ) {
    assert( nullptr != seedPoints );

    const unsigned int mult = 1812433253ul;
    unsigned int       seed = 5489ul;
    for (unsigned int i = 0; i < len; ++i) {
        seedPoints[ i ] = seed;
        seed = mult * (seed ^ (seed >> 30)) + (i + 1);
    }
}

static void mersenne_twister_vector_update(unsigned int* const p) {
    static const unsigned int A[ 2 ] = { 0, 0x9908B0DF };
    unsigned int i=0;
    for (; i < N - M; i++)
        p[i] = p[i + (M)] ^ (((p[i] & 0x80000000) | (p[i + 1] & 0x7FFFFFFF)) >> 1) ^ A[p[i + 1] & 1];
    for (; i < N - 1; i++)
        p[i] = p[i + (M - N)] ^ (((p[i] & 0x80000000) | (p[i + 1] & 0x7FFFFFFF)) >> 1) ^ A[p[i + 1] & 1];
    p[N - 1] = p[M - 1] ^ (((p[N - 1] & 0x80000000) | (p[0] & 0x7FFFFFFF)) >> 1) ^ A[p[0] & 1];
}

unsigned int mersenne_twister() {
    // State-vector
    static unsigned int  vector[ N ];
    // readout index
    static int           idx = N + 1;

    if (static_cast<unsigned int>(idx) >= N) {
        if (static_cast<unsigned int>(idx) > N) {
            mersenne_twister_vector_init(vector, N);
        }
        mersenne_twister_vector_update(vector);
        idx = 0;
    }
    unsigned int e = vector[ idx++ ];

    // Tempering
    e ^= (e >> 11);
    e ^= (e << 7)  & 0x9D2C5680;
    e ^= (e << 15) & 0xEFC60000;
    e ^= (e >> 18);

    return e;
}

RandomGenerator::RandomGenerator( GeneratorType type ) noexcept
: m_type( type ) {
    ::srand( static_cast< unsigned int >( time( NULL ) ) );
}

RandomGenerator::~RandomGenerator() {
    // empty
}

int RandomGenerator::get( int lower, int upper ) {
    int ret( 0 );
    if ( GeneratorType::Standard == m_type ) {
        ret = ::rand() % upper + lower;
    } else if (GeneratorType::MersenneTwister == m_type) {
        ret = mersenne_twister() % upper + lower;
    }

    return ret;
}

} // Namespace CPPCore
<commit_msg>Update RandomGenerator.cpp<commit_after>/*-----------------------------------------------------------------------------------------------
The MIT License (MIT)

Copyright (c) 2014-2016 Kim Kulling

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-----------------------------------------------------------------------------------------------*/
#include <cppcore/Random/RandomGenerator.h>

#include <stdlib.h>
#include <time.h>
#include <cassert>

namespace CPPCore {

static const unsigned int N = 624;
static const unsigned int M = 397;

static void mersenne_twister_vector_init( unsigned int *seedPoints, size_t len ) {
    assert( nullptr != seedPoints );

    const unsigned int mult = 1812433253ul;
    unsigned int       seed = 5489ul;
    for (size_t i = 0; i < len; ++i) {
        seedPoints[ i ] = seed;
        seed = mult * (seed ^ (seed >> 30)) + (i + 1);
    }
}

static void mersenne_twister_vector_update(unsigned int* const p) {
    static const unsigned int A[ 2 ] = { 0, 0x9908B0DF };
    unsigned int i=0;
    for (; i < N - M; i++) {
        p[i] = p[i + (M)] ^ (((p[i] & 0x80000000) | (p[i + 1] & 0x7FFFFFFF)) >> 1) ^ A[p[i + 1] & 1];
    }
    for (; i < N - 1; i++) {
        p[i] = p[i + (M - N)] ^ (((p[i] & 0x80000000) | (p[i + 1] & 0x7FFFFFFF)) >> 1) ^ A[p[i + 1] & 1];
    }
    p[N - 1] = p[M - 1] ^ (((p[N - 1] & 0x80000000) | (p[0] & 0x7FFFFFFF)) >> 1) ^ A[p[0] & 1];
}

unsigned int mersenne_twister() {
    // State-vector
    static unsigned int  vector[ N ];
    // readout index
    static int           idx = N + 1;

    if (static_cast<unsigned int>(idx) >= N) {
        if (static_cast<unsigned int>(idx) > N) {
            mersenne_twister_vector_init(vector, N);
        }
        mersenne_twister_vector_update(vector);
        idx = 0;
    }
    unsigned int e = vector[ idx++ ];

    // Tempering
    e ^= (e >> 11);
    e ^= (e << 7)  & 0x9D2C5680;
    e ^= (e << 15) & 0xEFC60000;
    e ^= (e >> 18);

    return e;
}

RandomGenerator::RandomGenerator( GeneratorType type ) noexcept :
        m_type( type ) {
    ::srand( static_cast<unsigned int>(time(nullptr)));
}

RandomGenerator::~RandomGenerator() {
    // empty
}

int RandomGenerator::get( int lower, int upper ) {
    int ret( 0 );
    if ( GeneratorType::Standard == m_type ) {
        ret = ::rand() % upper + lower;
    } else if (GeneratorType::MersenneTwister == m_type) {
        ret = mersenne_twister() % upper + lower;
    }

    return ret;
}

} // Namespace CPPCore
<|endoftext|>


<commit_before>/******************************************************************************************************
  July 10, 2017

  Ian A. Cosden
  Princeton University
  icosden@princeton.edu

  Sample Matrix-Matrix multiplication code for CoDaS-HEP Summer School

  Purpose:
     To use as a example to profile with performance tuning tools such as VTune.  The code does
     not do anything useful and is for illustrative/educational use only.  It is not meant to be
     exhaustive or demostrating optimal matrix-matrix multiplication techniques.

  Description:
     Code generates two matrices with random numbers.  They are stored in 2D arrays (named A and B) as
     well as 1D arrays (a and b).  There are 4 functions that multiply A and B and store the result in
     matrix C (or c in the 1D case).  It is possible to set the percentage of time each function is
     called via the command line.

  Command line arguments:
      N <threshold 1> <threshold 2> <threshold 3>

      N: size of NxN matrix
      **optional**:
      thresholds: 4 functions are distributed between 0 and 1.
      mm1 is called between 0 and <threshold 1>
      mm2 is called between <threshold 1> and <threshold 2>
      mm3 is called between <threshold 2> and <threshold 3>
      mm4 is called between <threshold 3> and 1.

      Example:
        to call only mm1 use 1.0 0   0
        to call only mm2 use 0   1.0 1.0
        to call only mm3 use 0   0   1.0
        to call only mm4 use 0   0   0

*******************************************************************************************************/

#include "mm.h"

int main(int argc, char *argv[])
{

	int matrix_size; //N*N matrix
	double thresh_1, thresh_2, thresh_3;

	//read command line input
	//set various paramaters
	if(argc<2) {
		cout<<"ERROR: expecting integer matrix size, i.e., N for NxN matrix"<<endl;
		exit(1);
	}
	else {
		matrix_size=atoi(argv[1]);
	}

	if(argc<5) {
		thresh_1=0.1;
		thresh_2=0.3;
		thresh_3=0.6;
		cout<<"Using default thresholds: ";
	}
	else {
		thresh_1=atof(argv[2]);
		thresh_2=atof(argv[3]);
		thresh_3=atof(argv[4]);
		cout<<"Using user supplied thresholds: ";
	}

	cout<<thresh_1<<" "<<thresh_2<<" "<<thresh_3<<endl;
	cout<<"using matrix size:"<<matrix_size<<endl;

	mkl_set_num_threads(1); //needed to prevent mkl (mm4) from grabbing all available cores

	double **A, **B, **C; //2D arrays
	double *a, *b, *c;    //equivalent 1D arrays

	A = new double*[matrix_size];
	B = new double*[matrix_size];
	C = new double*[matrix_size];
	a = new double[matrix_size*matrix_size];
	b = new double[matrix_size*matrix_size];
	c = new double[matrix_size*matrix_size];

	for (int i = 0 ; i < matrix_size; i++) {
		A[i] = new double[matrix_size];
		B[i] = new double[matrix_size];
		C[i] = new double[matrix_size];
	}

	int idx;

	//initialize values crudely between 0 and 1
	//(we don't really care what they are)
	for (int i=0; i<matrix_size; i++) {
		idx=i*matrix_size;
		for (int j = 0 ; j < matrix_size; j++) {
			A[i][j]=((double) rand() / (RAND_MAX));
			B[i][j]=((double) rand() / (RAND_MAX));
			C[i][j]=0.0;
			a[idx+j]=A[i][j];
			b[idx+j]=B[i][j];
			c[idx+j]=0.0;
		}
	}

	int max_iters=50;  //number of times to call a matrix-matrix (mm) function
	double random_choice; //random number from rng

	//Depending on random number and earlier set thresholds call a matrix-multiplication
	//function mm1,mm2,mm3,mm4.  This is done to purposely obfuscate the "hotspots"
	for (int r=0; r < max_iters; r++) {
		random_choice = ((double) rand() / (RAND_MAX));
		if (random_choice<thresh_1) {
			zero_result(C,matrix_size);
			mm1(A,B,C,matrix_size);
		}
		else if (random_choice>=thresh_1 && random_choice<thresh_2) {
			zero_result(C,matrix_size);
			mm2(A,B,C,matrix_size);
		}
		else if (random_choice>=thresh_2 && random_choice<thresh_3) {
			zero_result_1D(c,matrix_size);
			mm3(a,b,c,matrix_size);
		}
		else {
			zero_result_1D(c,matrix_size);
			mm4(a,b,c,matrix_size);
		}
	}

	for (int i = 0 ; i < matrix_size; i++)  {
		delete A[i];
		delete B[i];
		delete C[i];
	}

	delete A;
	delete B;
	delete C;

	return 0;
}
<commit_msg>added rng seed<commit_after>/******************************************************************************************************
  July 10, 2017

  Ian A. Cosden
  Princeton University
  icosden@princeton.edu

  Sample Matrix-Matrix multiplication code for CoDaS-HEP Summer School

  Purpose:
     To use as a example to profile with performance tuning tools such as VTune.  The code does
     not do anything useful and is for illustrative/educational use only.  It is not meant to be
     exhaustive or demostrating optimal matrix-matrix multiplication techniques.

  Description:
     Code generates two matrices with random numbers.  They are stored in 2D arrays (named A and B) as
     well as 1D arrays (a and b).  There are 4 functions that multiply A and B and store the result in
     matrix C (or c in the 1D case).  It is possible to set the percentage of time each function is
     called via the command line.

  Command line arguments:
      N <threshold 1> <threshold 2> <threshold 3>

      N: size of NxN matrix
      **optional**:
      thresholds: 4 functions are distributed between 0 and 1.
      mm1 is called between 0 and <threshold 1>
      mm2 is called between <threshold 1> and <threshold 2>
      mm3 is called between <threshold 2> and <threshold 3>
      mm4 is called between <threshold 3> and 1.

      Example:
        to call only mm1 use 1.0 0   0
        to call only mm2 use 0   1.0 1.0
        to call only mm3 use 0   0   1.0
        to call only mm4 use 0   0   0

*******************************************************************************************************/

#include "mm.h"

int main(int argc, char *argv[])
{

	int matrix_size; //N*N matrix
	double thresh_1, thresh_2, thresh_3;

	//read command line input
	//set various paramaters
	if(argc<2) {
		cout<<"ERROR: expecting integer matrix size, i.e., N for NxN matrix"<<endl;
		exit(1);
	}
	else {
		matrix_size=atoi(argv[1]);
	}

	if(argc<5) {
		thresh_1=0.1;
		thresh_2=0.3;
		thresh_3=0.6;
		cout<<"Using default thresholds: ";
	}
	else {
		thresh_1=atof(argv[2]);
		thresh_2=atof(argv[3]);
		thresh_3=atof(argv[4]);
		cout<<"Using user supplied thresholds: ";
	}

	cout<<thresh_1<<" "<<thresh_2<<" "<<thresh_3<<endl;
	cout<<"using matrix size:"<<matrix_size<<endl;

	mkl_set_num_threads(1); //needed to prevent mkl (mm4) from grabbing all available cores

	double **A, **B, **C; //2D arrays
	double *a, *b, *c;    //equivalent 1D arrays

	A = new double*[matrix_size];
	B = new double*[matrix_size];
	C = new double*[matrix_size];
	a = new double[matrix_size*matrix_size];
	b = new double[matrix_size*matrix_size];
	c = new double[matrix_size*matrix_size];

	for (int i = 0 ; i < matrix_size; i++) {
		A[i] = new double[matrix_size];
		B[i] = new double[matrix_size];
		C[i] = new double[matrix_size];
	}

	int idx;

	//initialize values crudely between 0 and 1
	//(we don't really care what they are)
	for (int i=0; i<matrix_size; i++) {
		idx=i*matrix_size;
		for (int j = 0 ; j < matrix_size; j++) {
			A[i][j]=((double) rand() / (RAND_MAX));
			B[i][j]=((double) rand() / (RAND_MAX));
			C[i][j]=0.0;
			a[idx+j]=A[i][j];
			b[idx+j]=B[i][j];
			c[idx+j]=0.0;
		}
	}

	int max_iters=50;  //number of times to call a matrix-matrix (mm) function
	double random_choice; //random number from rng
	srand (time(NULL));

	//Depending on random number and earlier set thresholds call a matrix-multiplication
	//function mm1,mm2,mm3,mm4.  This is done to purposely obfuscate the "hotspots"
	for (int r=0; r < max_iters; r++) {
		random_choice = ((double) rand() / (RAND_MAX));
		if (random_choice<thresh_1) {
			zero_result(C,matrix_size);
			mm1(A,B,C,matrix_size);
		}
		else if (random_choice>=thresh_1 && random_choice<thresh_2) {
			zero_result(C,matrix_size);
			mm2(A,B,C,matrix_size);
		}
		else if (random_choice>=thresh_2 && random_choice<thresh_3) {
			zero_result_1D(c,matrix_size);
			mm3(a,b,c,matrix_size);
		}
		else {
			zero_result_1D(c,matrix_size);
			mm4(a,b,c,matrix_size);
		}
	}

	for (int i = 0 ; i < matrix_size; i++)  {
		delete A[i];
		delete B[i];
		delete C[i];
	}

	delete A;
	delete B;
	delete C;

	return 0;
}
<|endoftext|>


<commit_before>#include "../include/ex_utilities.hpp"

int main()
{
    Vector v;
    Vector v2(4);

    v.Print("empty vect");
    v2.Print("size 4 vect");

    int dim = 6;

    Vector zeros(dim, 0.0);
    Vector ones(dim, 1.0);
    Vector twos(dim, 2.0);

    std::cout << "Ones size: " << ones.size() << "\n";
    ones.Print("ones");

    zeros[0] = 2.0;
    zeros[1] *= 8.0;

    std::cout << "Modified 0th element: " << zeros[0] << " ";
    std::cout << "1st element: " << zeros[1] << "\n";

    Vector vect_from_file(linalgcpp::ReadText("vect.text"));
    vect_from_file.Print("From file");

    double ip = twos.Mult(ones);
    std::cout << "Inner product: " << ip << "\n";

    double norm = twos.L2Norm();
    std::cout << "Norm: " << norm << "\n";

    Vector twos_normalized = twos;
    twos_normalized /= norm;
    twos_normalized.Print("twos normalized");

    double two_ip = twos.Mult(twos);
    std::cout << "Twos Inner product: " << two_ip << "\n";

    Vector threes = twos;
    threes += ones;
    threes.Print("1 + 2");

    Vector fours = twos + twos;
    fours.Print("2 + 2");
}
<commit_msg>Fix vector example when parsing from file<commit_after>#include "../include/ex_utilities.hpp"

int main()
{
    Vector v;
    Vector v2(4);

    v.Print("empty vect");
    v2.Print("size 4 vect");

    int dim = 6;

    Vector zeros(dim, 0.0);
    Vector ones(dim, 1.0);
    Vector twos(dim, 2.0);

    std::cout << "Ones size: " << ones.size() << "\n";
    ones.Print("ones");

    zeros[0] = 2.0;
    zeros[1] *= 8.0;

    std::cout << "Modified 0th element: " << zeros[0] << " ";
    std::cout << "1st element: " << zeros[1] << "\n";

    Vector vect_from_file(linalgcpp::ReadText("data/vect4.txt"));
    vect_from_file.Print("From file");

    double ip = twos.Mult(ones);
    std::cout << "Inner product: " << ip << "\n";

    double norm = twos.L2Norm();
    std::cout << "Norm: " << norm << "\n";

    Vector twos_normalized = twos;
    twos_normalized /= norm;
    twos_normalized.Print("twos normalized");

    double two_ip = twos.Mult(twos);
    std::cout << "Twos Inner product: " << two_ip << "\n";

    Vector threes = twos;
    threes += ones;
    threes.Print("1 + 2");

    Vector fours = twos + twos;
    fours.Print("2 + 2");
}
<|endoftext|>


<commit_before>#pragma once

#include <memory>
#include <string>
#include <unordered_map>

#include "human_interface_device.hpp"

class event_grabber final {
public:
  event_grabber(void) {
    manager_ = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
    if (!manager_) {
      return;
    }

    auto device_matching_dictionaries = create_device_matching_dictionaries();
    if (device_matching_dictionaries) {
      IOHIDManagerSetDeviceMatchingMultiple(manager_, device_matching_dictionaries);
      CFRelease(device_matching_dictionaries);

      IOHIDManagerRegisterDeviceMatchingCallback(manager_, device_matching_callback, this);
      IOHIDManagerRegisterDeviceRemovalCallback(manager_, device_removal_callback, this);

      IOHIDManagerScheduleWithRunLoop(manager_, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    }
  }

  ~event_grabber(void) {
    if (manager_) {
      IOHIDManagerUnscheduleFromRunLoop(manager_, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
      CFRelease(manager_);
      manager_ = nullptr;
    }
  }

private:
  CFDictionaryRef _Nonnull create_device_matching_dictionary(uint32_t usage_page, uint32_t usage) {
    auto device_matching_dictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    if (!device_matching_dictionary) {
      goto finish;
    }

    // usage_page
    if (!usage_page) {
      goto finish;
    } else {
      auto number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage_page);
      if (!number) {
        goto finish;
      }
      CFDictionarySetValue(device_matching_dictionary, CFSTR(kIOHIDDeviceUsagePageKey), number);
      CFRelease(number);
    }

    // usage (The usage is only valid if the usage page is also defined)
    if (!usage) {
      goto finish;
    } else {
      auto number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage);
      if (!number) {
        goto finish;
      }
      CFDictionarySetValue(device_matching_dictionary, CFSTR(kIOHIDDeviceUsageKey), number);
      CFRelease(number);
    }

  finish:
    return device_matching_dictionary;
  }

  CFArrayRef _Nullable create_device_matching_dictionaries(void) {
    auto device_matching_dictionaries = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
    if (!device_matching_dictionaries) {
      return nullptr;
    }

    // kHIDUsage_GD_Keyboard
    {
      auto device_matching_dictionary = create_device_matching_dictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard);
      if (device_matching_dictionary) {
        CFArrayAppendValue(device_matching_dictionaries, device_matching_dictionary);
        CFRelease(device_matching_dictionary);
      }
    }

#if 0
    // kHIDUsage_GD_Mouse
    {
      auto device_matching_dictionary = create_device_matching_dictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse);
      if (device_matching_dictionary) {
        CFArrayAppendValue(device_matching_dictionaries, device_matching_dictionary);
        CFRelease(device_matching_dictionary);
      }
    }
#endif

    return device_matching_dictionaries;
  }

  static void device_matching_callback(void* _Nullable context, IOReturn result, void* _Nullable sender, IOHIDDeviceRef _Nonnull device) {
    if (result != kIOReturnSuccess) {
      return;
    }

    auto self = static_cast<event_grabber*>(context);
    if (!self) {
      return;
    }

    if (!device) {
      return;
    }

    auto dev = std::make_shared<human_interface_device>(device);
    if (!dev) {
      return;
    }

    std::cout << "matching: " << std::endl
              << "  vendor_id:0x" << std::hex << dev->get_vendor_id() << std::endl
              << "  product_id:0x" << std::hex << dev->get_product_id() << std::endl
              << "  location_id:0x" << std::hex << dev->get_location_id() << std::endl
              << "  serial_number:" << dev->get_serial_number_string() << std::endl
              << "  " << dev->get_manufacturer() << std::endl
              << "  " << dev->get_product() << std::endl;

    if (dev->get_serial_number_string() == "org.pqrs.driver.VirtualHIDKeyboard") {
      dev->open();
      self->virtual_keyboard_ = dev;
    } else {
      //if (dev->get_manufacturer() != "pqrs.org") {
      if (dev->get_manufacturer() == "Apple Inc.") {
        dev->grab(queue_value_available_callback, self);
      }
    }

    (self->hids_)[device] = dev;
  }

  static void device_removal_callback(void* _Nullable context, IOReturn result, void* _Nullable sender, IOHIDDeviceRef _Nonnull device) {
    if (result != kIOReturnSuccess) {
      return;
    }

    auto self = static_cast<event_grabber*>(context);
    if (!self) {
      return;
    }

    if (!device) {
      return;
    }

    auto it = (self->hids_).find(device);
    if (it == (self->hids_).end()) {
      std::cout << "unknown device has been removed" << std::endl;
    } else {
      auto dev = it->second;
      if (dev) {
        std::cout << "removal vendor_id:0x" << std::hex << dev->get_vendor_id() << " product_id:0x" << std::hex << dev->get_product_id() << std::endl;
        (self->hids_).erase(it);
      }
    }
  }

  static void queue_value_available_callback(void* _Nullable context, IOReturn result, void* _Nullable sender) {
    std::cout << "queue_value_available_callback" << std::endl;

    auto queue = static_cast<IOHIDQueueRef>(sender);
    while (true) {
      auto value = IOHIDQueueCopyNextValueWithTimeout(queue, 0.);
      if (!value) {
        break;
      }

      std::cout << "value arrived" << std::endl;
      CFRelease(value);
    }
  }

  IOHIDManagerRef _Nullable manager_;
  std::unordered_map<IOHIDDeviceRef, std::shared_ptr<human_interface_device>> hids_;
  std::weak_ptr<human_interface_device> virtual_keyboard_;
};
<commit_msg>dump element information<commit_after>#pragma once

#include <memory>
#include <string>
#include <unordered_map>

#include "human_interface_device.hpp"

class event_grabber final {
public:
  event_grabber(void) {
    manager_ = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
    if (!manager_) {
      return;
    }

    auto device_matching_dictionaries = create_device_matching_dictionaries();
    if (device_matching_dictionaries) {
      IOHIDManagerSetDeviceMatchingMultiple(manager_, device_matching_dictionaries);
      CFRelease(device_matching_dictionaries);

      IOHIDManagerRegisterDeviceMatchingCallback(manager_, device_matching_callback, this);
      IOHIDManagerRegisterDeviceRemovalCallback(manager_, device_removal_callback, this);

      IOHIDManagerScheduleWithRunLoop(manager_, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    }
  }

  ~event_grabber(void) {
    if (manager_) {
      IOHIDManagerUnscheduleFromRunLoop(manager_, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
      CFRelease(manager_);
      manager_ = nullptr;
    }
  }

private:
  CFDictionaryRef _Nonnull create_device_matching_dictionary(uint32_t usage_page, uint32_t usage) {
    auto device_matching_dictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    if (!device_matching_dictionary) {
      goto finish;
    }

    // usage_page
    if (!usage_page) {
      goto finish;
    } else {
      auto number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage_page);
      if (!number) {
        goto finish;
      }
      CFDictionarySetValue(device_matching_dictionary, CFSTR(kIOHIDDeviceUsagePageKey), number);
      CFRelease(number);
    }

    // usage (The usage is only valid if the usage page is also defined)
    if (!usage) {
      goto finish;
    } else {
      auto number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage);
      if (!number) {
        goto finish;
      }
      CFDictionarySetValue(device_matching_dictionary, CFSTR(kIOHIDDeviceUsageKey), number);
      CFRelease(number);
    }

  finish:
    return device_matching_dictionary;
  }

  CFArrayRef _Nullable create_device_matching_dictionaries(void) {
    auto device_matching_dictionaries = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
    if (!device_matching_dictionaries) {
      return nullptr;
    }

    // kHIDUsage_GD_Keyboard
    {
      auto device_matching_dictionary = create_device_matching_dictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard);
      if (device_matching_dictionary) {
        CFArrayAppendValue(device_matching_dictionaries, device_matching_dictionary);
        CFRelease(device_matching_dictionary);
      }
    }

#if 0
    // kHIDUsage_GD_Mouse
    {
      auto device_matching_dictionary = create_device_matching_dictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse);
      if (device_matching_dictionary) {
        CFArrayAppendValue(device_matching_dictionaries, device_matching_dictionary);
        CFRelease(device_matching_dictionary);
      }
    }
#endif

    return device_matching_dictionaries;
  }

  static void device_matching_callback(void* _Nullable context, IOReturn result, void* _Nullable sender, IOHIDDeviceRef _Nonnull device) {
    if (result != kIOReturnSuccess) {
      return;
    }

    auto self = static_cast<event_grabber*>(context);
    if (!self) {
      return;
    }

    if (!device) {
      return;
    }

    auto dev = std::make_shared<human_interface_device>(device);
    if (!dev) {
      return;
    }

    std::cout << "matching: " << std::endl
              << "  vendor_id:0x" << std::hex << dev->get_vendor_id() << std::endl
              << "  product_id:0x" << std::hex << dev->get_product_id() << std::endl
              << "  location_id:0x" << std::hex << dev->get_location_id() << std::endl
              << "  serial_number:" << dev->get_serial_number_string() << std::endl
              << "  " << dev->get_manufacturer() << std::endl
              << "  " << dev->get_product() << std::endl;

    if (dev->get_serial_number_string() == "org.pqrs.driver.VirtualHIDKeyboard") {
      dev->open();
      self->virtual_keyboard_ = dev;
    } else {
      //if (dev->get_manufacturer() != "pqrs.org") {
      if (dev->get_manufacturer() == "Apple Inc.") {
        dev->grab(queue_value_available_callback, self);
      }
    }

    (self->hids_)[device] = dev;
  }

  static void device_removal_callback(void* _Nullable context, IOReturn result, void* _Nullable sender, IOHIDDeviceRef _Nonnull device) {
    if (result != kIOReturnSuccess) {
      return;
    }

    auto self = static_cast<event_grabber*>(context);
    if (!self) {
      return;
    }

    if (!device) {
      return;
    }

    auto it = (self->hids_).find(device);
    if (it == (self->hids_).end()) {
      std::cout << "unknown device has been removed" << std::endl;
    } else {
      auto dev = it->second;
      if (dev) {
        std::cout << "removal vendor_id:0x" << std::hex << dev->get_vendor_id() << " product_id:0x" << std::hex << dev->get_product_id() << std::endl;
        (self->hids_).erase(it);
      }
    }
  }

  static void queue_value_available_callback(void* _Nullable context, IOReturn result, void* _Nullable sender) {
    auto queue = static_cast<IOHIDQueueRef>(sender);
    while (true) {
      auto value = IOHIDQueueCopyNextValueWithTimeout(queue, 0.);
      if (!value) {
        break;
      }

      auto element = IOHIDValueGetElement(value);
      auto integerValue = IOHIDValueGetIntegerValue(value);

      if (element) {
        auto usagePage = IOHIDElementGetUsagePage(element);
        auto usage = IOHIDElementGetUsage(element);

        std::cout << "element" << std::endl
                  << "  usagePage:0x" << std::hex << usagePage << std::endl
                  << "  usage:0x" << std::hex << usage << std::endl
                  << "  type:" << IOHIDElementGetType(element) << std::endl
                  << "  integerValue:" << integerValue << std::endl
          ;
      }

      std::cout << "value arrived" << std::endl;
      CFRelease(value);
    }
  }

  IOHIDManagerRef _Nullable manager_;
  std::unordered_map<IOHIDDeviceRef, std::shared_ptr<human_interface_device>> hids_;
  std::weak_ptr<human_interface_device> virtual_keyboard_;
};
<|endoftext|>


<commit_before><commit_msg>flattening custom types ranges<commit_after><|endoftext|>


<commit_before>#include <initializer_list>
#include <map>
#include <sstream>
#include <string>

#include <gtk/gtk.h>

/// List of unit types we handle.
enum class ConversionUnit
{
    Inch,
    Point,
    Twip,

    M,
    Cm,
    Mm,
    Mm100,

    Emu
};

/// Hold references to all data needed to perform a conversion.
class Conversion
{
  public:
    GtkEntry* _amount;
    GtkComboBox* _from;
    GtkComboBox* _to;
    GtkLabel* _result;

    Conversion();
};

Conversion::Conversion()
    : _amount(nullptr), _from(nullptr), _to(nullptr), _result(nullptr)
{
}

namespace
{

void initAmount(GtkWidget* grid, Conversion& conversion)
{
    GtkWidget* amount = gtk_entry_new();
    conversion._amount = GTK_ENTRY(amount);
    gtk_grid_attach(GTK_GRID(grid), amount, 0, 0, 1, 1);
}

GtkComboBox* initUnit(GtkWidget* grid, int active, int top)
{
    GtkWidget* unitCombo = gtk_combo_box_text_new();
    std::initializer_list<std::string> units = {"inch",  "point", "twip",

                                                "m",     "cm",    "mm",
                                                "mm100",

                                                "emu"};
    for (const auto& unit : units)
        gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(unitCombo), nullptr,
                                  unit.c_str());
    gtk_combo_box_set_active(GTK_COMBO_BOX(unitCombo), active);
    gtk_grid_attach(GTK_GRID(grid), unitCombo, 1, top, 1, 1);
    return GTK_COMBO_BOX(unitCombo);
}

void initResult(GtkWidget* grid, Conversion& conversion)
{
    GtkWidget* result = gtk_label_new("");
    conversion._result = GTK_LABEL(result);
    gtk_label_set_selectable(conversion._result, TRUE);
    gtk_grid_attach(GTK_GRID(grid), result, 0, 1, 1, 1);
}

void convert(GtkWidget* /*widget*/, gpointer userData)
{
    Conversion* conversion = static_cast<Conversion*>(userData);
    static std::map<ConversionUnit, double> units;
    if (units.empty())
    {
        units[ConversionUnit::Inch] = 914400.0;
        units[ConversionUnit::Point] = 914400.0 / 72;
        units[ConversionUnit::Twip] = 914400.0 / 72 / 20;

        units[ConversionUnit::M] = 360 * 100000;
        units[ConversionUnit::Cm] = 360 * 1000;
        units[ConversionUnit::Mm] = 360 * 100;
        units[ConversionUnit::Mm100] = 360;

        units[ConversionUnit::Emu] = 1;
    }

    std::string text;
    // Convert to EMU.
    try
    {
        double amount = std::stod(gtk_entry_get_text(conversion->_amount));
        auto from = static_cast<ConversionUnit>(
            gtk_combo_box_get_active(conversion->_from));
        double emu = amount * units[from];

        auto to = static_cast<ConversionUnit>(
            gtk_combo_box_get_active(conversion->_to));
        double ret = emu / units[to];
        text = std::to_string(ret);
    }
    catch (const std::invalid_argument& exception)
    {
        std::stringstream ss;
        ss << "invalid argument: " << exception.what();
        text = ss.str();
    }

    gtk_label_set_text(conversion->_result, text.c_str());
}

void initConvert(GtkWidget* grid, Conversion& conversion)
{
    GtkWidget* convertButton = gtk_button_new_with_label("Convert");
    gtk_grid_attach(GTK_GRID(grid), convertButton, 0, 2, 1, 1);
    g_signal_connect(convertButton, "clicked", G_CALLBACK(convert),
                     &conversion);
}

void initQuit(GtkWidget* grid)
{
    GtkWidget* quit = gtk_button_new_with_label("Quit");
    g_signal_connect(quit, "clicked", G_CALLBACK(gtk_main_quit), nullptr);
    gtk_grid_attach(GTK_GRID(grid), quit, 1, 2, 1, 1);
}

void initControls(GtkWidget* window, Conversion& conversion)
{
    GtkWidget* grid = gtk_grid_new();
    initAmount(grid, conversion);
    conversion._from = initUnit(grid, 0, 0);
    conversion._to = initUnit(grid, 1, 1);
    initResult(grid, conversion);
    initConvert(grid, conversion);
    initQuit(grid);
    gtk_container_add(GTK_CONTAINER(window), grid);
}

} // anonymous namespace

int main(int argc, char** argv)
{
    gtk_init(&argc, &argv);
    GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "gtktpconv");
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), nullptr);

    Conversion conversion;
    initControls(window, conversion);

    gtk_widget_show_all(window);

    gtk_main();

    return 0;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>gtktpconv: separate UI and logic pieces<commit_after>#include <initializer_list>
#include <map>
#include <sstream>
#include <string>

#include <gtk/gtk.h>

namespace tpconv
{

/// List of unit types we handle.
enum class ConversionUnit
{
    Inch,
    Point,
    Twip,

    M,
    Cm,
    Mm,
    Mm100,

    Emu
};

/// List of string representation of ConversionUnit elements.
std::initializer_list<std::string> getUnitNames()
{
    static std::initializer_list<std::string> units = {"inch",  "point", "twip",

                                                       "m",     "cm",    "mm",
                                                       "mm100",

                                                       "emu"};
    return units;
}

double convert(double amount, ConversionUnit from, ConversionUnit to)
{
    static std::map<ConversionUnit, double> units;
    if (units.empty())
    {
        units[ConversionUnit::Inch] = 914400.0;
        units[ConversionUnit::Point] = 914400.0 / 72;
        units[ConversionUnit::Twip] = 914400.0 / 72 / 20;

        units[ConversionUnit::M] = 360 * 100000;
        units[ConversionUnit::Cm] = 360 * 1000;
        units[ConversionUnit::Mm] = 360 * 100;
        units[ConversionUnit::Mm100] = 360;

        units[ConversionUnit::Emu] = 1;
    }

    // Convert to EMU.
    double emu = amount * units[from];
    return emu / units[to];
}

} // namespace tpconv

/// Hold Gtk references to all data needed to perform a conversion.
class Conversion
{
    GtkEntry* _amount;
    GtkComboBox* _from;
    GtkComboBox* _to;
    GtkLabel* _result;

    void initAmount(GtkWidget* grid);
    static GtkComboBox* initUnit(GtkWidget* grid, int active, int top);
    void initResult(GtkWidget* grid);
    void initConvert(GtkWidget* grid);
    static void convert(GtkWidget* widget, gpointer userData);
    void convertImpl();
    static void initQuit(GtkWidget* grid);

  public:
    Conversion();
    void initControls(GtkWidget* window);
};

Conversion::Conversion()
    : _amount(nullptr), _from(nullptr), _to(nullptr), _result(nullptr)
{
}

void Conversion::initAmount(GtkWidget* grid)
{
    GtkWidget* amount = gtk_entry_new();
    _amount = GTK_ENTRY(amount);
    gtk_grid_attach(GTK_GRID(grid), amount, 0, 0, 1, 1);
}

GtkComboBox* Conversion::initUnit(GtkWidget* grid, int active, int top)
{
    GtkWidget* unitCombo = gtk_combo_box_text_new();
    for (const auto& unit : tpconv::getUnitNames())
        gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(unitCombo), nullptr,
                                  unit.c_str());
    gtk_combo_box_set_active(GTK_COMBO_BOX(unitCombo), active);
    gtk_grid_attach(GTK_GRID(grid), unitCombo, 1, top, 1, 1);
    return GTK_COMBO_BOX(unitCombo);
}

void Conversion::initResult(GtkWidget* grid)
{
    GtkWidget* result = gtk_label_new("");
    _result = GTK_LABEL(result);
    gtk_label_set_selectable(_result, TRUE);
    gtk_grid_attach(GTK_GRID(grid), result, 0, 1, 1, 1);
}

void Conversion::initConvert(GtkWidget* grid)
{
    GtkWidget* convertButton = gtk_button_new_with_label("Convert");
    gtk_grid_attach(GTK_GRID(grid), convertButton, 0, 2, 1, 1);
    g_signal_connect(convertButton, "clicked", G_CALLBACK(Conversion::convert),
                     this);
}

void Conversion::initControls(GtkWidget* window)
{
    GtkWidget* grid = gtk_grid_new();
    initAmount(grid);
    _from = Conversion::initUnit(grid, 0, 0);
    _to = Conversion::initUnit(grid, 1, 1);
    initResult(grid);
    initConvert(grid);
    initQuit(grid);
    gtk_container_add(GTK_CONTAINER(window), grid);
}

void Conversion::convert(GtkWidget* /*widget*/, gpointer userData)
{
    Conversion* conversion = static_cast<Conversion*>(userData);
    conversion->convertImpl();
}

void Conversion::convertImpl()
{
    std::string text;
    try
    {
        double amount = std::stod(gtk_entry_get_text(_amount));
        auto from = static_cast<tpconv::ConversionUnit>(
            gtk_combo_box_get_active(_from));
        auto to =
            static_cast<tpconv::ConversionUnit>(gtk_combo_box_get_active(_to));
        double ret = tpconv::convert(amount, from, to);
        text = std::to_string(ret);
    }
    catch (const std::invalid_argument& exception)
    {
        std::stringstream ss;
        ss << "invalid argument: " << exception.what();
        text = ss.str();
    }

    gtk_label_set_text(_result, text.c_str());
}

void Conversion::initQuit(GtkWidget* grid)
{
    GtkWidget* quit = gtk_button_new_with_label("Quit");
    g_signal_connect(quit, "clicked", G_CALLBACK(gtk_main_quit), nullptr);
    gtk_grid_attach(GTK_GRID(grid), quit, 1, 2, 1, 1);
}

int main(int argc, char** argv)
{
    gtk_init(&argc, &argv);
    GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_title(GTK_WINDOW(window), "gtktpconv");
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), nullptr);

    Conversion conversion;
    conversion.initControls(window);

    gtk_widget_show_all(window);

    gtk_main();

    return 0;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>