<commit_before>// © Copyright (c) 2018 SqYtCO

#include "graphiccore.h"
#include "core.h"
#include "openglwidget.h"
#include "hashlifesystem.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QStandardPaths>
#include <QLabel>
#include <filesystem>
#include <chrono>
#include <fstream>
#include <sstream>
#include <iomanip>					// std::put_time
#ifdef ENABLE_CALC_TIME_MEASUREMENT
#include <QDebug>
#endif

GraphicConfiguration GraphicCore::gconfig;
OpenGLWidget* GraphicCore::opengl;
QLabel* GraphicCore::gen_counter;
std::unique_ptr<std::thread> GraphicCore::stepping_thread;
std::atomic_bool GraphicCore::stepping_stop;
bool GraphicCore::stepping_block;
std::unique_ptr<std::thread> GraphicCore::generating_thread;
std::atomic_bool GraphicCore::generating_stop;
std::unique_ptr<std::thread> GraphicCore::calc_thread;
std::atomic_bool GraphicCore::calc_stop;
std::mutex GraphicCore::system_mutex;

void GraphicCore::init()
{
	// get correct config path
	QString config_path = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
	if(config_path[config_path.size() - 1] != '/')
		config_path.append('/');

	// set config paths
	Core::get_config()->set_config_path(config_path.toStdString());
	gconfig.set_config_path(config_path.toStdString());

	// create new system with correct configuration
	Core::new_system();

	stepping_stop = true;
	stepping_block = false;

	generating_stop = true;
}

void GraphicCore::init_gui(OpenGLWidget* opengl, QLabel* gen_counter)
{
	GraphicCore::opengl = opengl;

	GraphicCore::gen_counter = gen_counter;
	gen_counter->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
	gen_counter->setAlignment(Qt::AlignRight | Qt::AlignBottom);
	gen_counter->setWindowFlags(Qt::SubWindow);
	gen_counter->setForegroundRole(QPalette::BrightText);
	update_generation_counter();
}

void GraphicCore::reset_cells(Cell_State state)
{
	Core::reset_cells(state);
	update_generation_counter();
	update_opengl();
}

void GraphicCore::new_system()
{
	stop_step();
	stop_generating();
	wait_for_calculation();

	// generate new system and fill with random cells if it is set
	Core::new_system();

	update_generation_counter();
	update_opengl();
}

void GraphicCore::reset_movement()
{
	opengl->reset_movement();
}

void GraphicCore::update_generation_counter()
{
	gen_counter->setVisible(!gconfig.get_hide_generation_counter());
	gen_counter->setFont(QFont("", static_cast<int>(get_config()->get_generation_counter_size())));
	gen_counter->setText(QString::number(Core::get_generation()));
}

void GraphicCore::update_opengl()
{
	opengl->update();
}

void GraphicCore::read_save()
{
	QString selected_filter("Game of Life(*.gol)");
	Core::load(QFileDialog::getOpenFileName(nullptr, QFileDialog::tr("Select a file to open..."), GraphicCore::get_config()->get_save_path().c_str(), QFileDialog::tr("All Files(*);;Game of Life(*.gol)"), &selected_filter).toStdString());
	update_opengl();
	update_generation_counter();
}

void GraphicCore::write_save_as()
{
	// ask for file name
	QString selected_filter("Game of Life(*.gol)");
	QString file_name = QFileDialog::getSaveFileName(nullptr, QFileDialog::tr("Choose a file name to save..."), GraphicCore::get_config()->get_save_path().c_str(), QFileDialog::tr("All Files(*);;Game of Life(*.gol)"), &selected_filter);

	// return if no file name was entered
	if(file_name.isEmpty())
		return;

	// write save; warning if writing fails
	if(!Core::save(file_name.toStdString()))
		QMessageBox::warning(nullptr, QMessageBox::tr("Write Error"), QMessageBox::tr("Writing Save Failed!\nPlease Check Your Permissions."));
}

void GraphicCore::write_save()
{
	try
	{
		// check if path exists and create it if not
		if(!std::filesystem::exists(gconfig.get_save_path()))
		//if(!std::filesystem::exists(std::filesystem::current_path().append(gconfig.get_save_path())))
			if(!std::filesystem::create_directories(std::filesystem::current_path().append(gconfig.get_save_path())))
				throw std::runtime_error("");

		std::string file;
		// create string with current date
		std::time_t time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
		std::string date;
		std::ostringstream oss;
		oss << std::put_time(std::localtime(&time), "%F_%H-%M");	// %y-%m-%d_%H-%M = YY-MM-DD_HH-min
		date = oss.str();

		// attached num if file exists already
		std::size_t save_num = 0;
		while(true)
		{
			// first try without num
			if(save_num == 0)
				file = gconfig.get_save_path() + date + ".gol";
			else
				file = gconfig.get_save_path() + date + "_" + std::to_string(save_num) + ".gol";

			// check if file exists already
			std::ifstream in(file);
			// if file does not exist, break loop
			if(!in)
				break;
			else
				++save_num;
		}

		// write save; warning if writing fails
		if(!Core::save(file))
			throw std::runtime_error("");
	}
	catch(...)	// if write permission is not granted
	{
		QMessageBox::warning(nullptr, QMessageBox::tr("Write Error"), QMessageBox::tr("Writing Save Failed!\nPlease Check Your Permissions."));
	}
}

void GraphicCore::next_generations(std::size_t generations)
{
	while(generations)
	{
		if(stepping_stop)
			break;
		else
		{
			{
				std::lock_guard<decltype(system_mutex)> lock(system_mutex);
				generations -= Core::next_generation(generations);
			}
		}
	}

	stepping_stop = true;

	// send signals to main thread (update GUI)
	emit opengl->cell_changed();
	emit opengl->start_update();
}

void GraphicCore::step()
{
	wait_for_calculation();
	// stop last step
	stop_step();

	// if thread is not blocked, start new step
	if(!stepping_block)
	{
		stepping_stop = false;
		stepping_thread.reset(new std::thread(next_generations, gconfig.get_generations_per_step()));
	}
}

void GraphicCore::stop_step()
{
	stepping_stop = true;
	if(stepping_thread)
	{
		stepping_thread->join();
		stepping_thread.reset(nullptr);
	}
}

void GraphicCore::start_generating()
{
	if(generating_running())
		return;

	wait_for_calculation();
	stop_step();
	stepping_block = true;

	if(generating_thread)
		generating_thread->join();

	generating_stop = false;
	generating_thread.reset(new std::thread([&]()
	{
		while(!generating_stop)
		{
			std::this_thread::sleep_for(std::chrono::milliseconds(gconfig.get_delay()));

#ifdef ENABLE_CALC_TIME_MEASUREMENT
			auto begin = std::chrono::high_resolution_clock::now();
#endif
			{
				std::lock_guard<decltype(system_mutex)> lock(system_mutex);
				Core::next_generation();
			}
#ifdef ENABLE_CALC_TIME_MEASUREMENT
			auto end = std::chrono::high_resolution_clock::now();
			qDebug() << "calculating: " << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() << "µs";
#endif

			emit opengl->cell_changed();
			emit opengl->start_update();
		}
	}));

	emit opengl->generating_start_stop();
}

void GraphicCore::stop_generating()
{
	if(generating_stop)
		return;

	generating_stop = true;

	if(generating_thread)
		generating_thread->join();
	generating_thread.reset(nullptr);
	stepping_block = false;

	emit opengl->generating_start_stop();
}

void GraphicCore::calc_next_generation()
{
	if(generating_running())
		return;

	wait_for_calculation();

	calc_thread.reset(new std::thread([]()
	{
		{
			std::lock_guard<decltype(system_mutex)> lock(system_mutex);
			Core::calc_next_generation(gconfig.get_generations_per_step());
		}
		emit opengl->start_update();
	}));
}

void GraphicCore::wait_for_calculation()
{
	if(calc_thread)
	{
		calc_thread->join();
		calc_thread.reset(nullptr);
	}
}
<commit_msg>create_directories fix<commit_after>// © Copyright (c) 2018 SqYtCO

#include "graphiccore.h"
#include "core.h"
#include "openglwidget.h"
#include "hashlifesystem.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QStandardPaths>
#include <QLabel>
#include <filesystem>
#include <chrono>
#include <fstream>
#include <sstream>
#include <iomanip>					// std::put_time
#ifdef ENABLE_CALC_TIME_MEASUREMENT
#include <QDebug>
#endif

GraphicConfiguration GraphicCore::gconfig;
OpenGLWidget* GraphicCore::opengl;
QLabel* GraphicCore::gen_counter;
std::unique_ptr<std::thread> GraphicCore::stepping_thread;
std::atomic_bool GraphicCore::stepping_stop;
bool GraphicCore::stepping_block;
std::unique_ptr<std::thread> GraphicCore::generating_thread;
std::atomic_bool GraphicCore::generating_stop;
std::unique_ptr<std::thread> GraphicCore::calc_thread;
std::atomic_bool GraphicCore::calc_stop;
std::mutex GraphicCore::system_mutex;

void GraphicCore::init()
{
	// get correct config path
	QString config_path = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
	if(config_path[config_path.size() - 1] != '/')
		config_path.append('/');

	// set config paths
	Core::get_config()->set_config_path(config_path.toStdString());
	gconfig.set_config_path(config_path.toStdString());

	// create new system with correct configuration
	Core::new_system();

	stepping_stop = true;
	stepping_block = false;

	generating_stop = true;
}

void GraphicCore::init_gui(OpenGLWidget* opengl, QLabel* gen_counter)
{
	GraphicCore::opengl = opengl;

	GraphicCore::gen_counter = gen_counter;
	gen_counter->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
	gen_counter->setAlignment(Qt::AlignRight | Qt::AlignBottom);
	gen_counter->setWindowFlags(Qt::SubWindow);
	gen_counter->setForegroundRole(QPalette::BrightText);
	update_generation_counter();
}

void GraphicCore::reset_cells(Cell_State state)
{
	Core::reset_cells(state);
	update_generation_counter();
	update_opengl();
}

void GraphicCore::new_system()
{
	stop_step();
	stop_generating();
	wait_for_calculation();

	// generate new system and fill with random cells if it is set
	Core::new_system();

	update_generation_counter();
	update_opengl();
}

void GraphicCore::reset_movement()
{
	opengl->reset_movement();
}

void GraphicCore::update_generation_counter()
{
	gen_counter->setVisible(!gconfig.get_hide_generation_counter());
	gen_counter->setFont(QFont("", static_cast<int>(get_config()->get_generation_counter_size())));
	gen_counter->setText(QString::number(Core::get_generation()));
}

void GraphicCore::update_opengl()
{
	opengl->update();
}

void GraphicCore::read_save()
{
	QString selected_filter("Game of Life(*.gol)");
	Core::load(QFileDialog::getOpenFileName(nullptr, QFileDialog::tr("Select a file to open..."), GraphicCore::get_config()->get_save_path().c_str(), QFileDialog::tr("All Files(*);;Game of Life(*.gol)"), &selected_filter).toStdString());
	update_opengl();
	update_generation_counter();
}

void GraphicCore::write_save_as()
{
	// ask for file name
	QString selected_filter("Game of Life(*.gol)");
	QString file_name = QFileDialog::getSaveFileName(nullptr, QFileDialog::tr("Choose a file name to save..."), GraphicCore::get_config()->get_save_path().c_str(), QFileDialog::tr("All Files(*);;Game of Life(*.gol)"), &selected_filter);

	// return if no file name was entered
	if(file_name.isEmpty())
		return;

	// write save; warning if writing fails
	if(!Core::save(file_name.toStdString()))
		QMessageBox::warning(nullptr, QMessageBox::tr("Write Error"), QMessageBox::tr("Writing Save Failed!\nPlease Check Your Permissions."));
}

void GraphicCore::write_save()
{
	try
	{
		// check if path exists and create it if not
		if(!std::filesystem::exists(gconfig.get_save_path()) && !gconfig.get_save_path().empty())
		{
			std::string save_dir = gconfig.get_save_path();
			if(save_dir.back() == std::filesystem::path::preferred_separator)
				save_dir.pop_back();
			if(!std::filesystem::create_directories(save_dir))
				throw std::runtime_error("");
		}

		std::string file;
		// create string with current date
		std::time_t time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
		std::string date;
		std::ostringstream oss;
		oss << std::put_time(std::localtime(&time), "%F_%H-%M");	// %y-%m-%d_%H-%M = YY-MM-DD_HH-min
		date = oss.str();

		// attached num if file exists already
		std::size_t save_num = 0;
		while(true)
		{
			// first try without num
			if(save_num == 0)
				file = gconfig.get_save_path() + date + ".gol";
			else
				file = gconfig.get_save_path() + date + "_" + std::to_string(save_num) + ".gol";

			// check if file exists already
			std::ifstream in(file);
			// if file does not exist, break loop
			if(!in)
				break;
			else
				++save_num;
		}

		// write save; warning if writing fails
		if(!Core::save(file))
			throw std::runtime_error("");
	}
	catch(...)	// if write permission is not granted
	{
		QMessageBox::warning(nullptr, QMessageBox::tr("Write Error"), QMessageBox::tr("Writing Save Failed!\nPlease Check Your Permissions."));
	}
}

void GraphicCore::next_generations(std::size_t generations)
{
	while(generations)
	{
		if(stepping_stop)
			break;
		else
		{
			{
				std::lock_guard<decltype(system_mutex)> lock(system_mutex);
				generations -= Core::next_generation(generations);
			}
		}
	}

	stepping_stop = true;

	// send signals to main thread (update GUI)
	emit opengl->cell_changed();
	emit opengl->start_update();
}

void GraphicCore::step()
{
	wait_for_calculation();
	// stop last step
	stop_step();

	// if thread is not blocked, start new step
	if(!stepping_block)
	{
		stepping_stop = false;
		stepping_thread.reset(new std::thread(next_generations, gconfig.get_generations_per_step()));
	}
}

void GraphicCore::stop_step()
{
	stepping_stop = true;
	if(stepping_thread)
	{
		stepping_thread->join();
		stepping_thread.reset(nullptr);
	}
}

void GraphicCore::start_generating()
{
	if(generating_running())
		return;

	wait_for_calculation();
	stop_step();
	stepping_block = true;

	if(generating_thread)
		generating_thread->join();

	generating_stop = false;
	generating_thread.reset(new std::thread([&]()
	{
		while(!generating_stop)
		{
			std::this_thread::sleep_for(std::chrono::milliseconds(gconfig.get_delay()));

#ifdef ENABLE_CALC_TIME_MEASUREMENT
			auto begin = std::chrono::high_resolution_clock::now();
#endif
			{
				std::lock_guard<decltype(system_mutex)> lock(system_mutex);
				Core::next_generation();
			}
#ifdef ENABLE_CALC_TIME_MEASUREMENT
			auto end = std::chrono::high_resolution_clock::now();
			qDebug() << "calculating: " << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() << "µs";
#endif

			emit opengl->cell_changed();
			emit opengl->start_update();
		}
	}));

	emit opengl->generating_start_stop();
}

void GraphicCore::stop_generating()
{
	if(generating_stop)
		return;

	generating_stop = true;

	if(generating_thread)
		generating_thread->join();
	generating_thread.reset(nullptr);
	stepping_block = false;

	emit opengl->generating_start_stop();
}

void GraphicCore::calc_next_generation()
{
	if(generating_running())
		return;

	wait_for_calculation();

	calc_thread.reset(new std::thread([]()
	{
		{
			std::lock_guard<decltype(system_mutex)> lock(system_mutex);
			Core::calc_next_generation(gconfig.get_generations_per_step());
		}
		emit opengl->start_update();
	}));
}

void GraphicCore::wait_for_calculation()
{
	if(calc_thread)
	{
		calc_thread->join();
		calc_thread.reset(nullptr);
	}
}
<|endoftext|>


<commit_before>#ifndef TOKEN_TYPE_HPP
#define TOKEN_TYPE_HPP

#include <iostream>
#include <string>
#include <unordered_map>

#include "utils/util.hpp"
#include "utils/error.hpp"

/**
  \brief Possible types for Token.

  L: literal\n
  K: keyword (2+ chars)\n
  C: construct (1 char)
*/
enum TokenType: int {
  L_INTEGER = 100, L_FLOAT, L_BOOLEAN, L_STRING,

  K_DEFINE = 200,
  K_AS, K_IMPORT, K_EXPORT, K_ALL, K_FROM,
  K_FUNCTION, K_RETURN,
  K_DO, K_END,
  K_IF, K_ELSE,
  K_WHILE, K_FOR, K_BREAK, K_CONTINUE,
  K_FAT_ARROW, K_VOID, K_FOREIGN,
  K_TYPE, K_CONSTR, K_PUBLIC, K_PRIVATE, K_PROTECT, K_STATIC,
  K_THROW, K_TRY, K_CATCH,

  C_SEMI = 300, C_2POINT, C_QUESTION,
  C_PAREN_LEFT, C_PAREN_RIGHT,
  C_SQPAREN_LEFT, C_SQPAREN_RIGHT,

  FILE_END = 999,
  OPERATOR = 1,
  IDENTIFIER = 5,
  UNPROCESSED = 0
};

/// Overload for string concatenation
std::string operator+(const char* a, const TokenType& tt);
/// \copydoc operator+(const char*,const TokenType&)
std::string operator+(const TokenType& tt, const char* a);
/// \copydoc operator+(const char*,const TokenType&)
std::string operator+(std::string& a, const TokenType& tt);
/// \copydoc operator+(const char*,const TokenType&)
std::string operator+(const TokenType& tt, std::string& a);
/**
  \brief Allow TokenType to be printed using its pretty name.

  \sa getTokenTypeName
*/
std::ostream& operator<<(std::ostream& os, const TokenType& tt);

/**
  \brief Maps a construct's character to its respective TokenType.
*/
const std::unordered_map<char, TokenType> constructMap {
  {';', C_SEMI},
  {':', C_2POINT},
  {'(', C_PAREN_LEFT},
  {')', C_PAREN_RIGHT},
  {'[', C_SQPAREN_LEFT},
  {']', C_SQPAREN_RIGHT},
  {'?', C_QUESTION},
};

/**
  \brief Maps a keyword's text to its respective TokenType.
*/
const std::unordered_map<std::string, TokenType> keywordsMap {
  {"define", K_DEFINE},
  {"as", K_AS},
  {"import", K_IMPORT},
  {"export", K_EXPORT},
  {"all", K_ALL},
  {"from", K_FROM},
  {"function", K_FUNCTION},
  {"return", K_RETURN},
  {"do", K_DO},
  {"end", K_END},
  {"if", K_IF},
  {"else", K_ELSE},
  {"while", K_WHILE},
  {"for", K_FOR},
  {"break", K_BREAK},
  {"continue", K_CONTINUE},
  {"type", K_TYPE},
  {"constructor", K_CONSTR},
  {"public", K_PUBLIC},
  {"private", K_PRIVATE},
  {"protected", K_PROTECT},
  {"static", K_STATIC},
  {"throw", K_THROW},
  {"try", K_TRY},
  {"catch", K_CATCH},
  {"=>", K_FAT_ARROW},
  {"void", K_VOID},
  {"foreign", K_FOREIGN},
};

/**
  \brief Maps the second character in an escape sequence (eg the 'n' in \\n) to the actual escaped code.
*/
const std::unordered_map<char, char> singleCharEscapeSeqences {
  {'a', '\a'},
  {'b', '\b'},
  {'f', '\f'},
  {'n', '\n'},
  {'r', '\r'},
  {'t', '\t'},
  {'v', '\v'},
  {'\\', '\\'},
  {'\'', '\''},
  {'"', '\"'},
  {'?', '\?'},
};

/**
  \brief Pretty names for the TokenTypes that don't already have some.
*/
const static std::unordered_map<TokenType, std::string> tokenTypeMap {
  {L_INTEGER, "Integer"},
  {L_FLOAT, "Float"},
  {L_BOOLEAN, "Boolean"},
  {L_STRING, "String"},
  {C_SEMI, "Semicolon"},
  {C_2POINT, "Colon"},
  {C_QUESTION, "Question mark"},
  {C_PAREN_LEFT, "Left parenthesis"},
  {C_PAREN_RIGHT, "Right parenthesis"},
  {C_PAREN_LEFT, "Left square parenthesis"},
  {C_PAREN_RIGHT, "Right square parenthesis"},
  {FILE_END, "End of file"},
  {OPERATOR, "Operator"},
  {IDENTIFIER, "Identifier"},
  {UNPROCESSED, "Unprocessed?"}
};

/**
  \brief Attempt to get a TokenType from its pretty name.

  Example results:\n
    Boolean -> L_BOOLEAN\n
    if -> K_IF\n
    ; -> C_SEMI\n

  Reverse operation of getTokenTypeName.
  \sa getTokenTypeName
*/
TokenType getTokenTypeByName(const std::string& name);
/**
  \brief Attempt to get a pretty name from a TokenType.

  Reverse operation of getTokenTypeByName.
  \sa getTokenTypeByName
*/
std::string getTokenTypeName(TokenType tt);

#endif
<commit_msg>Add missing keywords<commit_after>#ifndef TOKEN_TYPE_HPP
#define TOKEN_TYPE_HPP

#include <iostream>
#include <string>
#include <unordered_map>

#include "utils/util.hpp"
#include "utils/error.hpp"

/**
  \brief Possible types for Token.

  L: literal\n
  K: keyword (2+ chars)\n
  C: construct (1 char)
*/
enum TokenType: int {
  L_INTEGER = 100, L_FLOAT, L_BOOLEAN, L_STRING,

  K_DEFINE = 200,
  K_AS, K_IMPORT, K_EXPORT, K_ALL, K_FROM,
  K_FUNCTION, K_RETURN,
  K_DO, K_END,
  K_IF, K_ELSE,
  K_WHILE, K_FOR, K_BREAK, K_CONTINUE,
  K_FAT_ARROW, K_VOID, K_FOREIGN,
  K_TYPE, K_INHERITS, K_CONSTR, K_METHOD,
  K_PUBLIC, K_PRIVATE, K_PROTECT, K_STATIC,
  K_THROW, K_TRY, K_CATCH,

  C_SEMI = 300, C_2POINT, C_QUESTION,
  C_PAREN_LEFT, C_PAREN_RIGHT,
  C_SQPAREN_LEFT, C_SQPAREN_RIGHT,

  FILE_END = 999,
  OPERATOR = 1,
  IDENTIFIER = 5,
  UNPROCESSED = 0
};

/// Overload for string concatenation
std::string operator+(const char* a, const TokenType& tt);
/// \copydoc operator+(const char*,const TokenType&)
std::string operator+(const TokenType& tt, const char* a);
/// \copydoc operator+(const char*,const TokenType&)
std::string operator+(std::string& a, const TokenType& tt);
/// \copydoc operator+(const char*,const TokenType&)
std::string operator+(const TokenType& tt, std::string& a);
/**
  \brief Allow TokenType to be printed using its pretty name.

  \sa getTokenTypeName
*/
std::ostream& operator<<(std::ostream& os, const TokenType& tt);

/**
  \brief Maps a construct's character to its respective TokenType.
*/
const std::unordered_map<char, TokenType> constructMap {
  {';', C_SEMI},
  {':', C_2POINT},
  {'(', C_PAREN_LEFT},
  {')', C_PAREN_RIGHT},
  {'[', C_SQPAREN_LEFT},
  {']', C_SQPAREN_RIGHT},
  {'?', C_QUESTION},
};

/**
  \brief Maps a keyword's text to its respective TokenType.
*/
const std::unordered_map<std::string, TokenType> keywordsMap {
  {"define", K_DEFINE},
  {"as", K_AS},
  {"import", K_IMPORT},
  {"export", K_EXPORT},
  {"all", K_ALL},
  {"from", K_FROM},
  {"function", K_FUNCTION},
  {"return", K_RETURN},
  {"do", K_DO},
  {"end", K_END},
  {"if", K_IF},
  {"else", K_ELSE},
  {"while", K_WHILE},
  {"for", K_FOR},
  {"break", K_BREAK},
  {"continue", K_CONTINUE},
  {"type", K_TYPE},
  {"inherits", K_INHERITS},
  {"method", K_METHOD},
  {"constructor", K_CONSTR},
  {"public", K_PUBLIC},
  {"private", K_PRIVATE},
  {"protected", K_PROTECT},
  {"static", K_STATIC},
  {"throw", K_THROW},
  {"try", K_TRY},
  {"catch", K_CATCH},
  {"=>", K_FAT_ARROW},
  {"void", K_VOID},
  {"foreign", K_FOREIGN},
};

/**
  \brief Maps the second character in an escape sequence (eg the 'n' in \\n) to the actual escaped code.
*/
const std::unordered_map<char, char> singleCharEscapeSeqences {
  {'a', '\a'},
  {'b', '\b'},
  {'f', '\f'},
  {'n', '\n'},
  {'r', '\r'},
  {'t', '\t'},
  {'v', '\v'},
  {'\\', '\\'},
  {'\'', '\''},
  {'"', '\"'},
  {'?', '\?'},
};

/**
  \brief Pretty names for the TokenTypes that don't already have some.
*/
const static std::unordered_map<TokenType, std::string> tokenTypeMap {
  {L_INTEGER, "Integer"},
  {L_FLOAT, "Float"},
  {L_BOOLEAN, "Boolean"},
  {L_STRING, "String"},
  {C_SEMI, "Semicolon"},
  {C_2POINT, "Colon"},
  {C_QUESTION, "Question mark"},
  {C_PAREN_LEFT, "Left parenthesis"},
  {C_PAREN_RIGHT, "Right parenthesis"},
  {C_PAREN_LEFT, "Left square parenthesis"},
  {C_PAREN_RIGHT, "Right square parenthesis"},
  {FILE_END, "End of file"},
  {OPERATOR, "Operator"},
  {IDENTIFIER, "Identifier"},
  {UNPROCESSED, "Unprocessed?"}
};

/**
  \brief Attempt to get a TokenType from its pretty name.

  Example results:\n
    Boolean -> L_BOOLEAN\n
    if -> K_IF\n
    ; -> C_SEMI\n

  Reverse operation of getTokenTypeName.
  \sa getTokenTypeName
*/
TokenType getTokenTypeByName(const std::string& name);
/**
  \brief Attempt to get a pretty name from a TokenType.

  Reverse operation of getTokenTypeByName.
  \sa getTokenTypeByName
*/
std::string getTokenTypeName(TokenType tt);

#endif
<|endoftext|>


<commit_before>/*  This file is part of the KDE project.

Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).

This library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2.1 or 3 of the License.

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

You should have received a copy of the GNU Lesser General Public License
along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "backend.h"
#include "backendnode.h"

#include "audiooutput.h"
#include "effect.h"
#include "mediaobject.h"
#include "videowidget.h"
#include "volumeeffect.h"

//windows specific (DirectX Media Object)
#include <dmo.h>

#include <QtCore/QSettings>
#include <QtCore/QSet>
#include <QtCore/QVariant>

#include <QtCore/QtPlugin>

QT_BEGIN_NAMESPACE

Q_EXPORT_PLUGIN2(phonon_ds9, Phonon::DS9::Backend);

namespace Phonon
{
    namespace DS9
    {
        bool Backend::AudioMoniker::operator==(const AudioMoniker &other)
        {
            return other->IsEqual(*this) == S_OK;
        }

        Backend::Backend(QObject *parent, const QVariantList &)
            : QObject(parent)
        {
			::CoInitialize(0);

            //registering meta types
            qRegisterMetaType<HRESULT>("HRESULT");
            qRegisterMetaType<Graph>("Graph");
        }

        Backend::~Backend()
        {
            m_audioOutputs.clear();
            m_audioEffects.clear();
			::CoUninitialize();
        }

        QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QList<QVariant> &args)
        {
            switch (c)
            {
            case MediaObjectClass:
                return new MediaObject(parent);
            case AudioOutputClass:
                return new AudioOutput(this, parent);
#ifndef QT_NO_PHONON_EFFECT
            case EffectClass:
                return new Effect(m_audioEffects[ args[0].toInt() ], parent);
#endif //QT_NO_PHONON_EFFECT
#ifndef QT_NO_PHONON_VIDEO
            case VideoWidgetClass:
                return new VideoWidget(qobject_cast<QWidget *>(parent));
#endif //QT_NO_PHONON_VIDEO
#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT
            case VolumeFaderEffectClass:
                return new VolumeEffect(parent);
#endif //QT_NO_PHONON_VOLUMEFADEREFFECT
            default:
                return 0;
            }
        }

        bool Backend::supportsVideo() const
        {
#ifndef QT_NO_PHONON_VIDEO
            return true;
#else
            return false;
#endif //QT_NO_PHONON_VIDEO
        }

        QStringList Backend::availableMimeTypes() const
        {
            QStringList ret;
            {
                QSettings settings(QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Multimedia\\mplayer2\\mime types"), QSettings::NativeFormat);
                ret += settings.childGroups();
            }
            {
                QSettings settings(QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Multimedia\\wmplayer\\mime types"), QSettings::NativeFormat);
                ret += settings.childGroups();
            }

            ret.removeDuplicates();
            ret.replaceInStrings("\\", "/");
            qSort(ret);
            return ret;
        }

		Filter Backend::getAudioOutputFilter(int index) const
		{
			Filter ret;
			if (index >= 0 && index < m_audioOutputs.count()) {
				m_audioOutputs.at(index)->BindToObject(0, 0, IID_IBaseFilter, reinterpret_cast<void**>(&ret));
			} else {
				//just return the default audio renderer (not directsound)
				ret = Filter(CLSID_AudioRender, IID_IBaseFilter);
			}
			return ret;
		}

        QList<int> Backend::objectDescriptionIndexes(Phonon::ObjectDescriptionType type) const
        {
            QList<int> ret;

            switch(type)
            {
            case Phonon::AudioOutputDeviceType:
                {
#ifdef Q_OS_WINCE
					ret << 0; // only one audio device with index 0
#else
					ComPointer<ICreateDevEnum> devEnum(CLSID_SystemDeviceEnum, IID_ICreateDevEnum);
					if (!devEnum) {
						return ret; //it is impossible to enumerate the devices
					}
                    ComPointer<IEnumMoniker> enumMon;
                    HRESULT hr = devEnum->CreateClassEnumerator(CLSID_AudioRendererCategory, enumMon.pparam(), 0);
                    if (FAILED(hr)) {
                        break;
                    }
                    AudioMoniker mon;

                    //let's reorder the devices so that directshound appears first
                    int nbds = 0; //number of directsound devices

                    while (S_OK == enumMon->Next(1, mon.pparam(), 0)) {
                        LPOLESTR str = 0;
                        mon->GetDisplayName(0,0,&str);
                        const QString name = QString::fromUtf16((unsigned short*)str);
						ComPointer<IMalloc> alloc;
						::CoGetMalloc(1, alloc.pparam());
                        alloc->Free(str);

                        int insert_pos = 0;
                        if (!m_audioOutputs.contains(mon)) {
                            insert_pos = m_audioOutputs.count();
                            m_audioOutputs.append(mon);
                        } else {
                            insert_pos = m_audioOutputs.indexOf(mon);
                        }

                        if (name.contains(QLatin1String("DirectSound"))) {
                            ret.insert(nbds++, insert_pos);
                        } else {
                            ret.append(insert_pos);
                        }
                    }
#endif
					break;
                }
#ifndef QT_NO_PHONON_EFFECT
            case Phonon::EffectType:
                {
                    m_audioEffects.clear();
                    ComPointer<IEnumDMO> enumDMO;
                    HRESULT hr = ::DMOEnum(DMOCATEGORY_AUDIO_EFFECT, DMO_ENUMF_INCLUDE_KEYED, 0, 0, 0, 0, enumDMO.pparam());
                    if (SUCCEEDED(hr)) {
                        CLSID clsid;
                        while (S_OK == enumDMO->Next(1, &clsid, 0, 0)) {
                            ret += m_audioEffects.count();
                            m_audioEffects.append(clsid);
                        }
                    }
                    break;
                }
                break;
#endif //QT_NO_PHONON_EFFECT
            default:
                break;
            }
			return ret;
        }

        QHash<QByteArray, QVariant> Backend::objectDescriptionProperties(Phonon::ObjectDescriptionType type, int index) const
        {
            QHash<QByteArray, QVariant> ret;
            switch (type)
            {
            case Phonon::AudioOutputDeviceType:
                {
#ifdef Q_OS_WINCE
					ret["name"] = QLatin1String("default audio device");
#else
                    const AudioMoniker &mon = m_audioOutputs[index];
                    LPOLESTR str = 0;
                    HRESULT hr = mon->GetDisplayName(0,0, &str);
                    if (SUCCEEDED(hr)) {
                        QString name = QString::fromUtf16((unsigned short*)str);
						ComPointer<IMalloc> alloc;
						::CoGetMalloc(1, alloc.pparam());
                        alloc->Free(str);
                        ret["name"] = name.mid(name.indexOf('\\') + 1);
					}
#endif
                }
                break;
#ifndef QT_NO_PHONON_EFFECT
            case Phonon::EffectType:
                {
                    WCHAR name[80]; // 80 is clearly stated in the MSDN doc
                    HRESULT hr = ::DMOGetName(m_audioEffects[index], name);
                    if (SUCCEEDED(hr)) {
                        ret["name"] = QString::fromUtf16((unsigned short*)name);
                    }
                }
                break;
#endif //QT_NO_PHONON_EFFECT
            default:
                break;
            }
			return ret;
        }

        bool Backend::endConnectionChange(QSet<QObject *> objects)
        {
            if (objects.isEmpty())
                return true;
            //end of a transaction
            for(QSet<QObject *>::const_iterator it = objects.begin(); it != objects.end(); ++it) {
                if (BackendNode *node = qobject_cast<BackendNode*>(*it)) {
                    MediaObject *mo = node->mediaObject();
                    if (mo) {
                        switch(mo->transactionState)
                        {
                        case Phonon::ErrorState:
                        case Phonon::StoppedState:
                        case Phonon::LoadingState:
                            //nothing to do
                            break;
                        case Phonon::PausedState:
                            mo->pause();
                            break;
                        default:
                            mo->play();
                            break;
                        }

                        return mo->state() != Phonon::ErrorState;
                    }
                }
            }

            return false;
        }

        bool Backend::startConnectionChange(QSet<QObject *> objects)
        {
            if (objects.isEmpty())
                return true;

            //let's save the state of the graph (before we stop it)
            for(QSet<QObject *>::const_iterator it = objects.begin(); it != objects.end(); ++it) {
                if (BackendNode *node = qobject_cast<BackendNode*>(*it)) {
                    if (MediaObject *mo = node->mediaObject()) {

                        if (mo->state() != Phonon::StoppedState) {
                            mo->transactionState = mo->state();
                            mo->ensureStopped(); //we have to stop the graph..
                            return true;
                        }
                    }
                }
            }

            return false;
        }

        bool Backend::connectNodes(QObject *_source, QObject *_sink)
        {
            BackendNode *source = qobject_cast<BackendNode*>(_source);
            if (!source) {
                return false;
            }
            BackendNode *sink = qobject_cast<BackendNode*>(_sink);
            if (!sink) {
                return false;
            }

            //setting the graph if needed
            if (source->mediaObject() == 0 && sink->mediaObject() == 0) {
                    //error: no graph selected
                    return false;
            } else if (source->mediaObject() && source->mediaObject() != sink->mediaObject()) {
                //this' graph becomes the common one
                source->mediaObject()->grabNode(sink);
            } else if (source->mediaObject() == 0) {
                //sink's graph becomes the common one
                sink->mediaObject()->grabNode(source);
            }

            return source->mediaObject()->connectNodes(source, sink);
        }

        bool Backend::disconnectNodes(QObject *_source, QObject *_sink)
        {
            BackendNode *source = qobject_cast<BackendNode*>(_source);
            if (!source) {
                return false;
            }
            BackendNode *sink = qobject_cast<BackendNode*>(_sink);
            if (!sink) {
                return false;
            }

            return source->mediaObject() == 0 ||
                source->mediaObject()->disconnectNodes(source, sink);
        }
    }
}

QT_END_NAMESPACE

#include "moc_backend.cpp"
<commit_msg>small mistake fixed in the detection of the connections<commit_after>/*  This file is part of the KDE project.

Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).

This library is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 2.1 or 3 of the License.

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

You should have received a copy of the GNU Lesser General Public License
along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "backend.h"
#include "backendnode.h"

#include "audiooutput.h"
#include "effect.h"
#include "mediaobject.h"
#include "videowidget.h"
#include "volumeeffect.h"

//windows specific (DirectX Media Object)
#include <dmo.h>

#include <QtCore/QSettings>
#include <QtCore/QSet>
#include <QtCore/QVariant>

#include <QtCore/QtPlugin>

QT_BEGIN_NAMESPACE

Q_EXPORT_PLUGIN2(phonon_ds9, Phonon::DS9::Backend);

namespace Phonon
{
    namespace DS9
    {
        bool Backend::AudioMoniker::operator==(const AudioMoniker &other)
        {
            return other->IsEqual(*this) == S_OK;
        }

        Backend::Backend(QObject *parent, const QVariantList &)
            : QObject(parent)
        {
			::CoInitialize(0);

            //registering meta types
            qRegisterMetaType<HRESULT>("HRESULT");
            qRegisterMetaType<Graph>("Graph");
        }

        Backend::~Backend()
        {
            m_audioOutputs.clear();
            m_audioEffects.clear();
			::CoUninitialize();
        }

        QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QList<QVariant> &args)
        {
            switch (c)
            {
            case MediaObjectClass:
                return new MediaObject(parent);
            case AudioOutputClass:
                return new AudioOutput(this, parent);
#ifndef QT_NO_PHONON_EFFECT
            case EffectClass:
                return new Effect(m_audioEffects[ args[0].toInt() ], parent);
#endif //QT_NO_PHONON_EFFECT
#ifndef QT_NO_PHONON_VIDEO
            case VideoWidgetClass:
                return new VideoWidget(qobject_cast<QWidget *>(parent));
#endif //QT_NO_PHONON_VIDEO
#ifndef QT_NO_PHONON_VOLUMEFADEREFFECT
            case VolumeFaderEffectClass:
                return new VolumeEffect(parent);
#endif //QT_NO_PHONON_VOLUMEFADEREFFECT
            default:
                return 0;
            }
        }

        bool Backend::supportsVideo() const
        {
#ifndef QT_NO_PHONON_VIDEO
            return true;
#else
            return false;
#endif //QT_NO_PHONON_VIDEO
        }

        QStringList Backend::availableMimeTypes() const
        {
            QStringList ret;
            {
                QSettings settings(QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Multimedia\\mplayer2\\mime types"), QSettings::NativeFormat);
                ret += settings.childGroups();
            }
            {
                QSettings settings(QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Multimedia\\wmplayer\\mime types"), QSettings::NativeFormat);
                ret += settings.childGroups();
            }

            ret.removeDuplicates();
            ret.replaceInStrings("\\", "/");
            qSort(ret);
            return ret;
        }

		Filter Backend::getAudioOutputFilter(int index) const
		{
			Filter ret;
			if (index >= 0 && index < m_audioOutputs.count()) {
				m_audioOutputs.at(index)->BindToObject(0, 0, IID_IBaseFilter, reinterpret_cast<void**>(&ret));
			} else {
				//just return the default audio renderer (not directsound)
				ret = Filter(CLSID_AudioRender, IID_IBaseFilter);
			}
			return ret;
		}

        QList<int> Backend::objectDescriptionIndexes(Phonon::ObjectDescriptionType type) const
        {
            QList<int> ret;

            switch(type)
            {
            case Phonon::AudioOutputDeviceType:
                {
#ifdef Q_OS_WINCE
					ret << 0; // only one audio device with index 0
#else
					ComPointer<ICreateDevEnum> devEnum(CLSID_SystemDeviceEnum, IID_ICreateDevEnum);
					if (!devEnum) {
						return ret; //it is impossible to enumerate the devices
					}
                    ComPointer<IEnumMoniker> enumMon;
                    HRESULT hr = devEnum->CreateClassEnumerator(CLSID_AudioRendererCategory, enumMon.pparam(), 0);
                    if (FAILED(hr)) {
                        break;
                    }
                    AudioMoniker mon;

                    //let's reorder the devices so that directshound appears first
                    int nbds = 0; //number of directsound devices

                    while (S_OK == enumMon->Next(1, mon.pparam(), 0)) {
                        LPOLESTR str = 0;
                        mon->GetDisplayName(0,0,&str);
                        const QString name = QString::fromUtf16((unsigned short*)str);
						ComPointer<IMalloc> alloc;
						::CoGetMalloc(1, alloc.pparam());
                        alloc->Free(str);

                        int insert_pos = 0;
                        if (!m_audioOutputs.contains(mon)) {
                            insert_pos = m_audioOutputs.count();
                            m_audioOutputs.append(mon);
                        } else {
                            insert_pos = m_audioOutputs.indexOf(mon);
                        }

                        if (name.contains(QLatin1String("DirectSound"))) {
                            ret.insert(nbds++, insert_pos);
                        } else {
                            ret.append(insert_pos);
                        }
                    }
#endif
					break;
                }
#ifndef QT_NO_PHONON_EFFECT
            case Phonon::EffectType:
                {
                    m_audioEffects.clear();
                    ComPointer<IEnumDMO> enumDMO;
                    HRESULT hr = ::DMOEnum(DMOCATEGORY_AUDIO_EFFECT, DMO_ENUMF_INCLUDE_KEYED, 0, 0, 0, 0, enumDMO.pparam());
                    if (SUCCEEDED(hr)) {
                        CLSID clsid;
                        while (S_OK == enumDMO->Next(1, &clsid, 0, 0)) {
                            ret += m_audioEffects.count();
                            m_audioEffects.append(clsid);
                        }
                    }
                    break;
                }
                break;
#endif //QT_NO_PHONON_EFFECT
            default:
                break;
            }
			return ret;
        }

        QHash<QByteArray, QVariant> Backend::objectDescriptionProperties(Phonon::ObjectDescriptionType type, int index) const
        {
            QHash<QByteArray, QVariant> ret;
            switch (type)
            {
            case Phonon::AudioOutputDeviceType:
                {
#ifdef Q_OS_WINCE
					ret["name"] = QLatin1String("default audio device");
#else
                    const AudioMoniker &mon = m_audioOutputs[index];
                    LPOLESTR str = 0;
                    HRESULT hr = mon->GetDisplayName(0,0, &str);
                    if (SUCCEEDED(hr)) {
                        QString name = QString::fromUtf16((unsigned short*)str);
						ComPointer<IMalloc> alloc;
						::CoGetMalloc(1, alloc.pparam());
                        alloc->Free(str);
                        ret["name"] = name.mid(name.indexOf('\\') + 1);
					}
#endif
                }
                break;
#ifndef QT_NO_PHONON_EFFECT
            case Phonon::EffectType:
                {
                    WCHAR name[80]; // 80 is clearly stated in the MSDN doc
                    HRESULT hr = ::DMOGetName(m_audioEffects[index], name);
                    if (SUCCEEDED(hr)) {
                        ret["name"] = QString::fromUtf16((unsigned short*)name);
                    }
                }
                break;
#endif //QT_NO_PHONON_EFFECT
            default:
                break;
            }
			return ret;
        }

        bool Backend::endConnectionChange(QSet<QObject *> objects)
        {
            if (objects.isEmpty())
                return true;
            //end of a transaction
            for(QSet<QObject *>::const_iterator it = objects.begin(); it != objects.end(); ++it) {
                if (BackendNode *node = qobject_cast<BackendNode*>(*it)) {
                    MediaObject *mo = node->mediaObject();
                    if (mo) {
                        switch(mo->transactionState)
                        {
                        case Phonon::ErrorState:
                        case Phonon::StoppedState:
                        case Phonon::LoadingState:
                            //nothing to do
                            break;
                        case Phonon::PausedState:
                            mo->pause();
                            break;
                        default:
                            mo->play();
                            break;
                        }

                        return mo->state() != Phonon::ErrorState;
                    }
                }
            }

            return false;
        }

        bool Backend::startConnectionChange(QSet<QObject *> objects)
        {
            if (objects.isEmpty())
                return true;

            //let's save the state of the graph (before we stop it)
            for(QSet<QObject *>::const_iterator it = objects.begin(); it != objects.end(); ++it) {
                if (BackendNode *node = qobject_cast<BackendNode*>(*it)) {
                    if (MediaObject *mo = node->mediaObject()) {
                        if (mo->state() != Phonon::StoppedState) {
                            mo->transactionState = mo->state();
                            mo->ensureStopped(); //we have to stop the graph..
                        }
                        return true;
                    }
                }
            }

            return false;
        }

        bool Backend::connectNodes(QObject *_source, QObject *_sink)
        {
            BackendNode *source = qobject_cast<BackendNode*>(_source);
            if (!source) {
                return false;
            }
            BackendNode *sink = qobject_cast<BackendNode*>(_sink);
            if (!sink) {
                return false;
            }

            //setting the graph if needed
            if (source->mediaObject() == 0 && sink->mediaObject() == 0) {
                    //error: no graph selected
                    return false;
            } else if (source->mediaObject() && source->mediaObject() != sink->mediaObject()) {
                //this' graph becomes the common one
                source->mediaObject()->grabNode(sink);
            } else if (source->mediaObject() == 0) {
                //sink's graph becomes the common one
                sink->mediaObject()->grabNode(source);
            }

            return source->mediaObject()->connectNodes(source, sink);
        }

        bool Backend::disconnectNodes(QObject *_source, QObject *_sink)
        {
            BackendNode *source = qobject_cast<BackendNode*>(_source);
            if (!source) {
                return false;
            }
            BackendNode *sink = qobject_cast<BackendNode*>(_sink);
            if (!sink) {
                return false;
            }

            return source->mediaObject() == 0 ||
                source->mediaObject()->disconnectNodes(source, sink);
        }
    }
}

QT_END_NAMESPACE

#include "moc_backend.cpp"
<|endoftext|>


<commit_before>#include "gen/wsdd.nsmap"
#include "wsddapi.h"

int main(int argc, char** argv)
{
	const char* host = "239.255.255.250";
	int port = 3702;

	// create answer listener
	struct soap* serv = soap_new1(SOAP_IO_UDP);
	serv->bind_flags=SO_REUSEADDR;
	serv->connect_flags = SO_BROADCAST;
	if (!soap_valid_socket(soap_bind(serv, NULL, port, 1000)))
	{
		soap_print_fault(serv, stderr);
		exit(1);
	}
	ip_mreq mcast;
	mcast.imr_multiaddr.s_addr = inet_addr(host);
	mcast.imr_interface.s_addr = htonl(INADDR_ANY);
	if (setsockopt(serv->master, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcast, sizeof(mcast))<0)
	{
		std::cout << "group membership failed:" << strerror(errno) << std::endl;
	}

	// send probe request
	struct soap* soap = soap_new();
	printf("call soap_wsdd_Probe\n");
	int res = soap_wsdd_Probe(soap,
	  SOAP_WSDD_ADHOC,      // mode
	  SOAP_WSDD_TO_TS,      // to a TS
	  "soap.udp://239.255.255.250:3702",         // address of TS
	  soap_wsa_rand_uuid(soap),                   // message ID
	  NULL,                 // ReplyTo
	  NULL,
	  NULL,
	  "");
	if (res != SOAP_OK)
	{
		soap_print_fault(soap, stderr);
	}

	// listen answers
	res = soap_wsdd_listen(serv, 5);
	if (res != SOAP_OK)
	{
		soap_print_fault(soap, stderr);
	}
	return 0;
}

soap_wsdd_mode wsdd_event_Resolve(struct soap *soap, const char *MessageID, const char *ReplyTo, const char *EndpointReference, struct wsdd__ResolveMatchType *match)
{
	printf("wsdd_event_Resolve\n");
	return SOAP_WSDD_ADHOC;
}

soap_wsdd_mode wsdd_event_Probe(struct soap *soap, const char *MessageID, const char *ReplyTo, const char *Types, const char *Scopes, const char *MatchBy, struct wsdd__ProbeMatchesType *matches)
{
	printf("wsdd_event_Probe id=%s types=%s scopes=%s\n", MessageID, Types, Scopes);
	return SOAP_WSDD_ADHOC;
}
<commit_msg>fix gsoap probe<commit_after>#include "gen/wsdd.nsmap"
#include "wsddapi.h"

int main(int argc, char** argv)
{
	const char* host = "239.255.255.250";
	int port = 3702;

	// create answer listener
	struct soap* serv = soap_new1(SOAP_IO_UDP);
	serv->bind_flags=SO_REUSEADDR;
	serv->connect_flags = SO_BROADCAST;
	if (!soap_valid_socket(soap_bind(serv, NULL, port, 1000)))
	{
		soap_print_fault(serv, stderr);
		exit(1);
	}
	ip_mreq mcast;
	mcast.imr_multiaddr.s_addr = inet_addr(host);
	mcast.imr_interface.s_addr = htonl(INADDR_ANY);
	if (setsockopt(serv->master, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcast, sizeof(mcast))<0)
	{
		std::cout << "group membership failed:" << strerror(errno) << std::endl;
	}

	// send probe request
	printf("call soap_wsdd_Probe\n");
	int res = soap_wsdd_Probe(serv,
	  SOAP_WSDD_ADHOC,      // mode
	  SOAP_WSDD_TO_TS,      // to a TS
	  "soap.udp://239.255.255.250:3702",         // address of TS
	  soap_wsa_rand_uuid(serv),                   // message ID
	  NULL,                 // ReplyTo
	  NULL,
	  NULL,
	  "");
	if (res != SOAP_OK)
	{
		soap_print_fault(serv, stderr);
	}

	// listen answers
	res = soap_wsdd_listen(serv, 5);
	if (res != SOAP_OK)
	{
		soap_print_fault(serv, stderr);
	}
	return 0;
}

soap_wsdd_mode wsdd_event_Resolve(struct soap *soap, const char *MessageID, const char *ReplyTo, const char *EndpointReference, struct wsdd__ResolveMatchType *match)
{
	printf("wsdd_event_Resolve\n");
	return SOAP_WSDD_ADHOC;
}

soap_wsdd_mode wsdd_event_Probe(struct soap *soap, const char *MessageID, const char *ReplyTo, const char *Types, const char *Scopes, const char *MatchBy, struct wsdd__ProbeMatchesType *matches)
{
	printf("wsdd_event_Probe id=%s types=%s scopes=%s\n", MessageID, Types, Scopes);
	return SOAP_WSDD_ADHOC;
}
<|endoftext|>


<commit_before>#include <QApplication>
#include <QStringList>
#include <QString>
#include <QDebug>

#include "wd.h"
#include "font.h"
#include "../base/state.h"

// ---------------------------------------------------------------------
Font::Font(string s)
{
  if (s=="fixfont") {
    font=config.Font;
    return;
  } else if (s=="profont") {
    font=QApplication::font();
    return;
  }
  angle=0;
  QString face, sizestyle;
  int bold=0,italic=0,strikeout=0,underline=0;
  float size=0;
  QString textstring = (QString::fromUtf8 (s.c_str())).simplified();
  if (textstring.startsWith("\"")) {
    QStringList ss=textstring.split("\"",QString::SkipEmptyParts);
    if (ss.length()>0) {
      face = ss[0];
      if (ss.length()>1) {
        sizestyle = ss[1];
        QStringList ss1=sizestyle.split(" ",QString::SkipEmptyParts);
        for (int j = 0; j < ss1.length(); j++) {
          if (ss1[j]=="bold") bold = 1;
          else if (ss1[j]=="italic") italic = 1;
          else if (ss1[j]=="underline") underline = 1;
          else if (ss1[j]=="strikeout") strikeout = 1;
          else if (ss1[j].mid(0,5)=="angle") angle = c_strtoi(q2s(ss1[j].mid(5)));
          else size = (float) c_strtod(q2s(ss1[j]));
        }
      }
    }
  } else {
    QStringList ss=textstring.split(" ",QString::SkipEmptyParts);
    if (ss.length()>0) {
      face = ss[0];
      if (ss.length()>1) {
        for (int j = 1; j < ss.length(); j++) {
          if (ss[j]=="bold") bold = 1;
          else if (ss[j]=="italic") italic = 1;
          else if (ss[j]=="underline") underline = 1;
          else if (ss[j]=="strikeout") strikeout = 1;
          else if (ss[j].mid(0,5)=="angle") angle = c_strtoi(q2s(ss[j].mid(5)));
          else size = (float) c_strtod(q2s(ss[j]));
        }
      }
    }
  }

//  qDebug() << "font: " + face + ",size=" + QString::number(size) + ",bold=" + QString::number(bold) + ",italic=" + QString::number(italic) + ",strikeout=" + QString::number(strikeout) + ",underline=" + QString::number(underline) + ",angle=" + QString::number(angle) ;
  font = QFont (face);
  if (0.0!=size) font.setPointSizeF((size>0.0)?size:-size);
  font.setBold(bold);
  font.setItalic(italic);
  font.setStrikeOut(strikeout);
  font.setUnderline(underline);
}

// ---------------------------------------------------------------------
Font::Font(string s,int size10, bool bold, bool italic, bool strikeout, bool underline, int angle10)
{
  angle=angle10;
  QString face = QString::fromUtf8 (s.c_str());
  font = QFont (face);
  font.setPointSizeF(size10/10);
  font.setBold(bold);
  font.setItalic(italic);
  font.setStrikeOut(strikeout);
  font.setUnderline(underline);
}
<commit_msg>ensure angle set in Font<commit_after>#include <QApplication>
#include <QStringList>
#include <QString>
#include <QDebug>

#include "wd.h"
#include "font.h"
#include "../base/state.h"

// ---------------------------------------------------------------------
Font::Font(string s)
{
  angle=0;
  if (s=="fixfont") {
    font=config.Font;
    return;
  } else if (s=="profont") {
    font=QApplication::font();
    return;
  }
  QString face, sizestyle;
  int bold=0,italic=0,strikeout=0,underline=0;
  float size=0;
  QString textstring = (QString::fromUtf8 (s.c_str())).simplified();
  if (textstring.startsWith("\"")) {
    QStringList ss=textstring.split("\"",QString::SkipEmptyParts);
    if (ss.length()>0) {
      face = ss[0];
      if (ss.length()>1) {
        sizestyle = ss[1];
        QStringList ss1=sizestyle.split(" ",QString::SkipEmptyParts);
        for (int j = 0; j < ss1.length(); j++) {
          if (ss1[j]=="bold") bold = 1;
          else if (ss1[j]=="italic") italic = 1;
          else if (ss1[j]=="underline") underline = 1;
          else if (ss1[j]=="strikeout") strikeout = 1;
          else if (ss1[j].mid(0,5)=="angle") angle = c_strtoi(q2s(ss1[j].mid(5)));
          else size = (float) c_strtod(q2s(ss1[j]));
        }
      }
    }
  } else {
    QStringList ss=textstring.split(" ",QString::SkipEmptyParts);
    if (ss.length()>0) {
      face = ss[0];
      if (ss.length()>1) {
        for (int j = 1; j < ss.length(); j++) {
          if (ss[j]=="bold") bold = 1;
          else if (ss[j]=="italic") italic = 1;
          else if (ss[j]=="underline") underline = 1;
          else if (ss[j]=="strikeout") strikeout = 1;
          else if (ss[j].mid(0,5)=="angle") angle = c_strtoi(q2s(ss[j].mid(5)));
          else size = (float) c_strtod(q2s(ss[j]));
        }
      }
    }
  }

//  qDebug() << "font: " + face + ",size=" + QString::number(size) + ",bold=" + QString::number(bold) + ",italic=" + QString::number(italic) + ",strikeout=" + QString::number(strikeout) + ",underline=" + QString::number(underline) + ",angle=" + QString::number(angle) ;
  font = QFont (face);
  if (0.0!=size) font.setPointSizeF((size>0.0)?size:-size);
  font.setBold(bold);
  font.setItalic(italic);
  font.setStrikeOut(strikeout);
  font.setUnderline(underline);
}

// ---------------------------------------------------------------------
Font::Font(string s,int size10, bool bold, bool italic, bool strikeout, bool underline, int angle10)
{
  angle=angle10;
  QString face = QString::fromUtf8 (s.c_str());
  font = QFont (face);
  font.setPointSizeF(size10/10);
  font.setBold(bold);
  font.setItalic(italic);
  font.setStrikeOut(strikeout);
  font.setUnderline(underline);
}
<|endoftext|>


<commit_before>#pragma once

#include "xml_parser_ctxt.hpp"
#include "pathname.hpp"
#include "libxml2_error_handlers.hpp"

#include <string>
#include <iosfwd>
#include <memory>

#include <libxml/tree.h>

class FreeXmlDoc {
public:
    auto operator( )( xmlDoc *xml ) const -> void { xmlFreeDoc( xml ); }
};

class XmlDoc {
    friend class XmlSchemaParserCtxt;
    friend class XsltDoc;

public:
    XmlDoc( );
    explicit XmlDoc( std::istream &is );
    XmlDoc( const XmlDoc &doc );
    XmlDoc( XmlDoc &&doc );
    auto operator=( const XmlDoc &rhs ) -> XmlDoc &;
    auto operator=( XmlDoc &&rhs ) -> XmlDoc &;
    explicit operator bool() const;
    auto get() const -> xmlDoc * { return xmlDoc_.get(); }
    friend auto operator>>( std::istream &is, XmlDoc &doc ) -> std::istream &;
    auto errorHandler( ) const -> const IErrorHandler & { return xmlHandler_; }
    auto toString( ) const -> std::string;
    auto swap( XmlDoc &other ) -> void;

private:
    std::unique_ptr<xmlDoc, FreeXmlDoc> xmlDoc_;
    XmlErrorHandler xmlHandler_;
};

auto fileToString( const std::string &path ) -> std::string;

inline auto operator<<( std::ostream &os, const XmlDoc &doc ) -> std::ostream & {
    os << doc.toString( );
    return os;
}

namespace std {
    template <>
    void swap( ::XmlDoc &lhs, XmlDoc &rhs );
}

<commit_msg>added friend class XPathCtxt<commit_after>#pragma once

#include "xml_parser_ctxt.hpp"
#include "pathname.hpp"
#include "libxml2_error_handlers.hpp"

#include <string>
#include <iosfwd>
#include <memory>

#include <libxml/tree.h>

class FreeXmlDoc {
public:
    auto operator( )( xmlDoc *xml ) const -> void { xmlFreeDoc( xml ); }
};

class XmlDoc {
    friend class XmlSchemaParserCtxt;
    friend class XsltDoc;
    friend class XPathCtxt;

public:
    XmlDoc( );
    explicit XmlDoc( std::istream &is );
    XmlDoc( const XmlDoc &doc );
    XmlDoc( XmlDoc &&doc );
    auto operator=( const XmlDoc &rhs ) -> XmlDoc &;
    auto operator=( XmlDoc &&rhs ) -> XmlDoc &;
    explicit operator bool() const;
    auto get() const -> xmlDoc * { return xmlDoc_.get(); }
    friend auto operator>>( std::istream &is, XmlDoc &doc ) -> std::istream &;
    auto errorHandler( ) const -> const IErrorHandler & { return xmlHandler_; }
    auto toString( ) const -> std::string;
    auto swap( XmlDoc &other ) -> void;

private:
    std::unique_ptr<xmlDoc, FreeXmlDoc> xmlDoc_;
    XmlErrorHandler xmlHandler_;
};

auto fileToString( const std::string &path ) -> std::string;

inline auto operator<<( std::ostream &os, const XmlDoc &doc ) -> std::ostream & {
    os << doc.toString( );
    return os;
}

namespace std {
    template <>
    void swap( ::XmlDoc &lhs, XmlDoc &rhs );
}

<|endoftext|>


<commit_before>#ifndef _EIGEN3_HDF5_HPP
#define _EIGEN3_HDF5_HPP

#include <array>
#include <cassert>
#include <complex>
#include <cstddef>
#include <stdexcept>
#include <string>
#include <vector>

//#include <hdf5.h>
#include <H5Cpp.h>
#include <Eigen/Dense>

namespace EigenHDF5
{

template <typename T>
struct DatatypeSpecialization;

// floating-point types

template <>
struct DatatypeSpecialization<float>
{
    static inline const H5::DataType * get (void)
        {
            return &H5::PredType::NATIVE_FLOAT;
        }
};

template <>
struct DatatypeSpecialization<double>
{
    static inline const H5::DataType * get (void)
        {
            return &H5::PredType::NATIVE_DOUBLE;
        }
};

template <>
struct DatatypeSpecialization<long double>
{
    static inline const H5::DataType * get (void)
        {
            return &H5::PredType::NATIVE_LDOUBLE;
        }
};

// integer types

template <>
struct DatatypeSpecialization<int>
{
    static inline const H5::DataType * get (void)
        {
            return &H5::PredType::NATIVE_INT;
        }
};

template <>
struct DatatypeSpecialization<unsigned int>
{
    static inline const H5::DataType * get (void)
        {
            return &H5::PredType::NATIVE_UINT;
        }
};

template <>
struct DatatypeSpecialization<long>
{
    static inline const H5::DataType * get (void)
        {
            return &H5::PredType::NATIVE_LONG;
        }
};

template <>
struct DatatypeSpecialization<unsigned long>
{
    static inline const H5::DataType * get (void)
        {
            return &H5::PredType::NATIVE_ULONG;
        }
};

// complex types
//
// inspired by http://www.mail-archive.com/hdf-forum@hdfgroup.org/msg00759.html

template <typename T>
class ComplexH5Type : public H5::CompType
{
public:
    ComplexH5Type (void)
        : CompType(sizeof(std::complex<T>))
        {
            const H5::DataType * const datatype = DatatypeSpecialization<T>::get();
            assert(datatype->getSize() == sizeof(T));
            // If we call the members "r" and "i", h5py interprets the
            // structure correctly as complex numbers.
            this->insertMember(std::string("r"), 0, *datatype);
            this->insertMember(std::string("i"), sizeof(T), *datatype);
            this->pack();
        }

    static const ComplexH5Type<T> * get_singleton (void)
        {
            // NOTE: constructing this could be a race condition
            static ComplexH5Type<T> singleton;
            return &singleton;
        }
};

template <typename T>
struct DatatypeSpecialization<std::complex<T> >
{
    static inline const H5::DataType * get (void)
        {
            return ComplexH5Type<T>::get_singleton();
        }
};

// string types, to be used mainly for attributes

template <>
struct DatatypeSpecialization<const char *>
{
    static inline const H5::DataType * get (void)
        {
            static const H5::StrType strtype(0, H5T_VARIABLE);
            return &strtype;
        }
};

template <>
struct DatatypeSpecialization<char *>
{
    static inline const H5::DataType * get (void)
        {
            static const H5::StrType strtype(0, H5T_VARIABLE);
            return &strtype;
        }
};

// XXX: for some unknown reason the following two functions segfault if
// H5T_VARIABLE is used.  The passed strings should still be null-terminated,
// so this is a bit worrisome.

template <std::size_t N>
struct DatatypeSpecialization<const char [N]>
{
    static inline const H5::DataType * get (void)
        {
            static const H5::StrType strtype(0, N);
            return &strtype;
        }
};

template <std::size_t N>
struct DatatypeSpecialization<char [N]>
{
    static inline const H5::DataType * get (void)
        {
            static const H5::StrType strtype(0, N);
            return &strtype;
        }
};

namespace internal
{
    template <typename Derived>
    H5::DataSpace create_dataspace (const Eigen::EigenBase<Derived> &mat)
    {
        const std::array<hsize_t, 2> dimensions = { {
            static_cast<hsize_t>(mat.rows()),
            static_cast<hsize_t>(mat.cols())
        } };
        return H5::DataSpace(dimensions.size(), dimensions.data());
    }
}

template <typename T>
void save_scalar_attribute (H5::H5Location &h5obj, const std::string &name, const T &value)
{
    const H5::DataType * const datatype = DatatypeSpecialization<T>::get();
    H5::DataSpace dataspace(H5S_SCALAR);
    H5::Attribute att = h5obj.createAttribute(name, *datatype, dataspace);
    att.write(*datatype, &value);
}

template <>
inline void save_scalar_attribute (H5::H5Location &h5obj, const std::string &name, const std::string &value)
{
    save_scalar_attribute(h5obj, name, value.c_str());
}

// see http://eigen.tuxfamily.org/dox/TopicFunctionTakingEigenTypes.html

template <typename Derived>
void save (H5::CommonFG &h5group, const std::string &name, const Eigen::EigenBase<Derived> &mat, const H5::DSetCreatPropList &plist=H5::DSetCreatPropList::DEFAULT)
{
    typedef typename Derived::Scalar Scalar;
    const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> row_major_mat(mat);
    const H5::DataSpace dataspace = internal::create_dataspace(mat);
    const H5::DataType * const datatype = DatatypeSpecialization<Scalar>::get();
    H5::DataSet dataset = h5group.createDataSet(name, *datatype, dataspace, plist);
    dataset.write(row_major_mat.data(), *datatype);
}

template <typename Derived>
void save_attribute (H5::H5Location &h5obj, const std::string &name, const Eigen::EigenBase<Derived> &mat)
{
    typedef typename Derived::Scalar Scalar;
    const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> row_major_mat(mat);
    const H5::DataSpace dataspace = internal::create_dataspace(mat);
    const H5::DataType * const datatype = DatatypeSpecialization<Scalar>::get();
    H5::Attribute dataset = h5obj.createAttribute(name, *datatype, dataspace);
    dataset.write(*datatype, row_major_mat.data());
}

namespace internal
{
    // H5::Attribute and H5::DataSet both have similar API's, and although they
    // share a common base class, the relevant methods are not virtual.  Worst
    // of all, they take their arguments in different orders!

    template <typename Scalar>
    inline void read_data (const H5::DataSet &dataset, Scalar *data, const H5::DataType &datatype)
    {
        dataset.read(data, datatype);
    }

    template <typename Scalar>
    inline void read_data (const H5::Attribute &dataset, Scalar *data, const H5::DataType &datatype)
    {
        dataset.read(datatype, data);
    }

    template <typename Derived, typename DataSet>
    void _load (const DataSet &dataset, const Eigen::DenseBase<Derived> &mat)
    {
        typedef typename Derived::Scalar Scalar;
        const H5::DataSpace dataspace = dataset.getSpace();
        const std::size_t ndims = dataspace.getSimpleExtentNdims();
        assert(ndims > 0);
        std::array<hsize_t, 2> dimensions;
        dimensions[1] = 1; // in case it's 1D
        if (ndims > dimensions.size()) {
            throw std::runtime_error("HDF5 array has too many dimensions.");
        }
        dataspace.getSimpleExtentDims(dimensions.data());
        const hsize_t rows = dimensions[0], cols = dimensions[1];
        std::vector<Scalar> data(rows * cols);
        const H5::DataType * const datatype = DatatypeSpecialization<Scalar>::get();
        internal::read_data(dataset, data.data(), *datatype);
        // see http://eigen.tuxfamily.org/dox/TopicFunctionTakingEigenTypes.html
        Eigen::DenseBase<Derived> &mat_ = const_cast<Eigen::DenseBase<Derived> &>(mat);
        mat_.derived().resize(rows, cols);
        mat_ = Eigen::Map<Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> >(data.data(), rows, cols);
    }

}

template <typename Derived>
void load (const H5::CommonFG &h5group, const std::string &name, const Eigen::DenseBase<Derived> &mat)
{
    const H5::DataSet dataset = h5group.openDataSet(name);
    internal::_load(dataset, mat);
}

template <typename Derived>
void load_attribute (const H5::H5Location &h5obj, const std::string &name, const Eigen::DenseBase<Derived> &mat)
{
    const H5::Attribute dataset = h5obj.openAttribute(name);
    internal::_load(dataset, mat);
}

} // namespace EigenHDF5

#endif
<commit_msg>apparently we can/should mark these H5Location references as const<commit_after>#ifndef _EIGEN3_HDF5_HPP
#define _EIGEN3_HDF5_HPP

#include <array>
#include <cassert>
#include <complex>
#include <cstddef>
#include <stdexcept>
#include <string>
#include <vector>

//#include <hdf5.h>
#include <H5Cpp.h>
#include <Eigen/Dense>

namespace EigenHDF5
{

template <typename T>
struct DatatypeSpecialization;

// floating-point types

template <>
struct DatatypeSpecialization<float>
{
    static inline const H5::DataType * get (void)
        {
            return &H5::PredType::NATIVE_FLOAT;
        }
};

template <>
struct DatatypeSpecialization<double>
{
    static inline const H5::DataType * get (void)
        {
            return &H5::PredType::NATIVE_DOUBLE;
        }
};

template <>
struct DatatypeSpecialization<long double>
{
    static inline const H5::DataType * get (void)
        {
            return &H5::PredType::NATIVE_LDOUBLE;
        }
};

// integer types

template <>
struct DatatypeSpecialization<int>
{
    static inline const H5::DataType * get (void)
        {
            return &H5::PredType::NATIVE_INT;
        }
};

template <>
struct DatatypeSpecialization<unsigned int>
{
    static inline const H5::DataType * get (void)
        {
            return &H5::PredType::NATIVE_UINT;
        }
};

template <>
struct DatatypeSpecialization<long>
{
    static inline const H5::DataType * get (void)
        {
            return &H5::PredType::NATIVE_LONG;
        }
};

template <>
struct DatatypeSpecialization<unsigned long>
{
    static inline const H5::DataType * get (void)
        {
            return &H5::PredType::NATIVE_ULONG;
        }
};

// complex types
//
// inspired by http://www.mail-archive.com/hdf-forum@hdfgroup.org/msg00759.html

template <typename T>
class ComplexH5Type : public H5::CompType
{
public:
    ComplexH5Type (void)
        : CompType(sizeof(std::complex<T>))
        {
            const H5::DataType * const datatype = DatatypeSpecialization<T>::get();
            assert(datatype->getSize() == sizeof(T));
            // If we call the members "r" and "i", h5py interprets the
            // structure correctly as complex numbers.
            this->insertMember(std::string("r"), 0, *datatype);
            this->insertMember(std::string("i"), sizeof(T), *datatype);
            this->pack();
        }

    static const ComplexH5Type<T> * get_singleton (void)
        {
            // NOTE: constructing this could be a race condition
            static ComplexH5Type<T> singleton;
            return &singleton;
        }
};

template <typename T>
struct DatatypeSpecialization<std::complex<T> >
{
    static inline const H5::DataType * get (void)
        {
            return ComplexH5Type<T>::get_singleton();
        }
};

// string types, to be used mainly for attributes

template <>
struct DatatypeSpecialization<const char *>
{
    static inline const H5::DataType * get (void)
        {
            static const H5::StrType strtype(0, H5T_VARIABLE);
            return &strtype;
        }
};

template <>
struct DatatypeSpecialization<char *>
{
    static inline const H5::DataType * get (void)
        {
            static const H5::StrType strtype(0, H5T_VARIABLE);
            return &strtype;
        }
};

// XXX: for some unknown reason the following two functions segfault if
// H5T_VARIABLE is used.  The passed strings should still be null-terminated,
// so this is a bit worrisome.

template <std::size_t N>
struct DatatypeSpecialization<const char [N]>
{
    static inline const H5::DataType * get (void)
        {
            static const H5::StrType strtype(0, N);
            return &strtype;
        }
};

template <std::size_t N>
struct DatatypeSpecialization<char [N]>
{
    static inline const H5::DataType * get (void)
        {
            static const H5::StrType strtype(0, N);
            return &strtype;
        }
};

namespace internal
{
    template <typename Derived>
    H5::DataSpace create_dataspace (const Eigen::EigenBase<Derived> &mat)
    {
        const std::array<hsize_t, 2> dimensions = { {
            static_cast<hsize_t>(mat.rows()),
            static_cast<hsize_t>(mat.cols())
        } };
        return H5::DataSpace(dimensions.size(), dimensions.data());
    }
}

template <typename T>
void save_scalar_attribute (const H5::H5Location &h5obj, const std::string &name, const T &value)
{
    const H5::DataType * const datatype = DatatypeSpecialization<T>::get();
    H5::DataSpace dataspace(H5S_SCALAR);
    H5::Attribute att = h5obj.createAttribute(name, *datatype, dataspace);
    att.write(*datatype, &value);
}

template <>
inline void save_scalar_attribute (const H5::H5Location &h5obj, const std::string &name, const std::string &value)
{
    save_scalar_attribute(h5obj, name, value.c_str());
}

// see http://eigen.tuxfamily.org/dox/TopicFunctionTakingEigenTypes.html

template <typename Derived>
void save (H5::CommonFG &h5group, const std::string &name, const Eigen::EigenBase<Derived> &mat, const H5::DSetCreatPropList &plist=H5::DSetCreatPropList::DEFAULT)
{
    typedef typename Derived::Scalar Scalar;
    const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> row_major_mat(mat);
    const H5::DataSpace dataspace = internal::create_dataspace(mat);
    const H5::DataType * const datatype = DatatypeSpecialization<Scalar>::get();
    H5::DataSet dataset = h5group.createDataSet(name, *datatype, dataspace, plist);
    dataset.write(row_major_mat.data(), *datatype);
}

template <typename Derived>
void save_attribute (const H5::H5Location &h5obj, const std::string &name, const Eigen::EigenBase<Derived> &mat)
{
    typedef typename Derived::Scalar Scalar;
    const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> row_major_mat(mat);
    const H5::DataSpace dataspace = internal::create_dataspace(mat);
    const H5::DataType * const datatype = DatatypeSpecialization<Scalar>::get();
    H5::Attribute dataset = h5obj.createAttribute(name, *datatype, dataspace);
    dataset.write(*datatype, row_major_mat.data());
}

namespace internal
{
    // H5::Attribute and H5::DataSet both have similar API's, and although they
    // share a common base class, the relevant methods are not virtual.  Worst
    // of all, they take their arguments in different orders!

    template <typename Scalar>
    inline void read_data (const H5::DataSet &dataset, Scalar *data, const H5::DataType &datatype)
    {
        dataset.read(data, datatype);
    }

    template <typename Scalar>
    inline void read_data (const H5::Attribute &dataset, Scalar *data, const H5::DataType &datatype)
    {
        dataset.read(datatype, data);
    }

    template <typename Derived, typename DataSet>
    void _load (const DataSet &dataset, const Eigen::DenseBase<Derived> &mat)
    {
        typedef typename Derived::Scalar Scalar;
        const H5::DataSpace dataspace = dataset.getSpace();
        const std::size_t ndims = dataspace.getSimpleExtentNdims();
        assert(ndims > 0);
        std::array<hsize_t, 2> dimensions;
        dimensions[1] = 1; // in case it's 1D
        if (ndims > dimensions.size()) {
            throw std::runtime_error("HDF5 array has too many dimensions.");
        }
        dataspace.getSimpleExtentDims(dimensions.data());
        const hsize_t rows = dimensions[0], cols = dimensions[1];
        std::vector<Scalar> data(rows * cols);
        const H5::DataType * const datatype = DatatypeSpecialization<Scalar>::get();
        internal::read_data(dataset, data.data(), *datatype);
        // see http://eigen.tuxfamily.org/dox/TopicFunctionTakingEigenTypes.html
        Eigen::DenseBase<Derived> &mat_ = const_cast<Eigen::DenseBase<Derived> &>(mat);
        mat_.derived().resize(rows, cols);
        mat_ = Eigen::Map<Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> >(data.data(), rows, cols);
    }

}

template <typename Derived>
void load (const H5::CommonFG &h5group, const std::string &name, const Eigen::DenseBase<Derived> &mat)
{
    const H5::DataSet dataset = h5group.openDataSet(name);
    internal::_load(dataset, mat);
}

template <typename Derived>
void load_attribute (const H5::H5Location &h5obj, const std::string &name, const Eigen::DenseBase<Derived> &mat)
{
    const H5::Attribute dataset = h5obj.openAttribute(name);
    internal::_load(dataset, mat);
}

} // namespace EigenHDF5

#endif
<|endoftext|>


<commit_before>#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <cstdio>
#include <cstdlib>

#include <map>
#include <string>

#include <gtk/gtk.h>

#define die(msg, ...) \
({fprintf(stderr, "gtkglswitch: fatal: " msg "\n", ##__VA_ARGS__); exit(1);})

static bool ask_user(const char procname[], bool &remember)
{
  GtkWidget *dialog = gtk_message_dialog_new (NULL,
      GTK_DIALOG_DESTROY_WITH_PARENT,
      GTK_MESSAGE_QUESTION,
      GTK_BUTTONS_OK,
      "Use OpenGL offloading for %s?", procname);
  GtkWidget *content = gtk_message_dialog_get_message_area(GTK_MESSAGE_DIALOG(dialog));

  GtkWidget *radioy = gtk_radio_button_new_with_label(NULL, "Yes, use the discrete GPU");
  gtk_container_add(GTK_CONTAINER(content), radioy);
  GtkWidget *radion = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radioy), "No, use integrated GPU");
  gtk_container_add(GTK_CONTAINER(content), radion);

  GtkWidget *check = gtk_check_button_new_with_label("Remember my choice");
  gtk_container_add(GTK_CONTAINER(content), check);
  gtk_widget_show_all(dialog);
  gtk_dialog_run(GTK_DIALOG (dialog));
  gboolean yes = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioy));
  remember = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check));
  gtk_widget_destroy(dialog);
  return yes;
}

static char *conffile;

static std::map<std::string, bool> read_memos()
{
  const char *configdir, *homedir;
  int r;
  if ((configdir = getenv("XDG_CONFIG_HOME")))
    r = asprintf(&conffile, "%s/libgl_switcheroo.conf", configdir);
  else if ((homedir = getenv("HOME")))
    r = asprintf(&conffile, "%s/.config/libgl_switcheroo.conf", homedir);
  else
    die("XDG_CONFIG_HOME and HOME are not set");
  if (r < 0)
    die("asprintf failed");
  FILE *f = fopen(conffile, "r");
  std::map<std::string, bool> memos;
  if (!f)
    return memos;
  char c, procname[17];
  while (fscanf(f, "%c%16[^\n]\n", &c, procname) == 2)
    memos[std::string(procname)] = c == '+';
  fclose(f);
  return memos;
}

static std::map<std::string, bool> memos(read_memos());

static bool lookup_memo(const char procname[], bool &choice)
{
  std::map<std::string, bool>::iterator i = memos.find(std::string(procname));
  if (i != memos.end())
    choice = i->second;
  return i != memos.end();
}

static void add_memo(const char procname[], bool choice)
{
  memos[std::string(procname)] = choice;
  FILE *f = fopen(conffile, "a");
  if (!f)
    die("failed to open %s for writing", conffile);
  fprintf(f, "%c%s\n", choice ? '+' : '-', procname);
  fclose(f);
}

static enum
{
  SWITCH_DEFAULT_ASK, SWITCH_DEFAULT_NO, SWITCH_DEFAULT_YES
} switch_default;

static bool need_switch(pid_t pid)
{
  char pathbuf[32];
  snprintf(pathbuf, 32, "/proc/%d/status", pid);
  int fd = open(pathbuf, O_RDONLY);
  char namebuf[32];
  read(fd, namebuf, 32);
  close(fd);
  *strchr(namebuf, '\n') = 0;
  char *procname = namebuf + 6;
  bool switch_yes;
  if (lookup_memo(procname, switch_yes))
    return switch_yes;
  if (switch_default != SWITCH_DEFAULT_ASK)
    return switch_default == SWITCH_DEFAULT_YES;
  bool remember = false;
  switch_yes = ask_user(procname, remember);
  if (remember)
    add_memo(procname, switch_yes);
  return switch_yes;
}

static void gdk_input_cb(void *data, int sock, GdkInputCondition cond)
{
  int fd = accept(sock, 0, 0);
  int pid;
  recv(fd, &pid, sizeof(pid), 0);
  pid = need_switch(pid);
  send(fd, &pid, sizeof(pid), 0);
  close(fd);
}

int main(int argc, char *argv[])
{
  char *opt_default = NULL;
  GError *error = NULL;
  static GOptionEntry entries[] = {
    {"default", 'D', 0, G_OPTION_ARG_STRING, &opt_default, "assume default answer", ""},
    {NULL}
  };
  if (!gtk_init_with_args (&argc, &argv, NULL, entries, NULL, &error))
    die("GTK initialization failed: %s", error->message);
  if (opt_default)
    if (!strcmp(opt_default, "yes"))
      switch_default = SWITCH_DEFAULT_YES;
    else if (!strcmp(opt_default, "no"))
      switch_default = SWITCH_DEFAULT_NO;
    else
      die("invalid default answer: %s", opt_default);

  struct sockaddr_un addr;
  addr.sun_family = AF_UNIX;
  snprintf(addr.sun_path, sizeof(addr.sun_path), "/tmp/libgl-switcheroo-%s/socket", getenv("USER"));
  unlink(addr.sun_path);
  int sock = socket(PF_UNIX, SOCK_STREAM, 0);
  if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    die("failed to bind socket %s: %s", addr.sun_path, strerror(errno));
  listen(sock, 16);
  gdk_input_add(sock, GDK_INPUT_READ, gdk_input_cb, NULL);
  gtk_main();

  return 0;
}
<commit_msg>Fix "ambiguous else" warning by expanding no-option case (GH-3)<commit_after>#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <cstdio>
#include <cstdlib>

#include <map>
#include <string>

#include <gtk/gtk.h>

#define die(msg, ...) \
({fprintf(stderr, "gtkglswitch: fatal: " msg "\n", ##__VA_ARGS__); exit(1);})

static bool ask_user(const char procname[], bool &remember)
{
  GtkWidget *dialog = gtk_message_dialog_new (NULL,
      GTK_DIALOG_DESTROY_WITH_PARENT,
      GTK_MESSAGE_QUESTION,
      GTK_BUTTONS_OK,
      "Use OpenGL offloading for %s?", procname);
  GtkWidget *content = gtk_message_dialog_get_message_area(GTK_MESSAGE_DIALOG(dialog));

  GtkWidget *radioy = gtk_radio_button_new_with_label(NULL, "Yes, use the discrete GPU");
  gtk_container_add(GTK_CONTAINER(content), radioy);
  GtkWidget *radion = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radioy), "No, use integrated GPU");
  gtk_container_add(GTK_CONTAINER(content), radion);

  GtkWidget *check = gtk_check_button_new_with_label("Remember my choice");
  gtk_container_add(GTK_CONTAINER(content), check);
  gtk_widget_show_all(dialog);
  gtk_dialog_run(GTK_DIALOG (dialog));
  gboolean yes = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(radioy));
  remember = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(check));
  gtk_widget_destroy(dialog);
  return yes;
}

static char *conffile;

static std::map<std::string, bool> read_memos()
{
  const char *configdir, *homedir;
  int r;
  if ((configdir = getenv("XDG_CONFIG_HOME")))
    r = asprintf(&conffile, "%s/libgl_switcheroo.conf", configdir);
  else if ((homedir = getenv("HOME")))
    r = asprintf(&conffile, "%s/.config/libgl_switcheroo.conf", homedir);
  else
    die("XDG_CONFIG_HOME and HOME are not set");
  if (r < 0)
    die("asprintf failed");
  FILE *f = fopen(conffile, "r");
  std::map<std::string, bool> memos;
  if (!f)
    return memos;
  char c, procname[17];
  while (fscanf(f, "%c%16[^\n]\n", &c, procname) == 2)
    memos[std::string(procname)] = c == '+';
  fclose(f);
  return memos;
}

static std::map<std::string, bool> memos(read_memos());

static bool lookup_memo(const char procname[], bool &choice)
{
  std::map<std::string, bool>::iterator i = memos.find(std::string(procname));
  if (i != memos.end())
    choice = i->second;
  return i != memos.end();
}

static void add_memo(const char procname[], bool choice)
{
  memos[std::string(procname)] = choice;
  FILE *f = fopen(conffile, "a");
  if (!f)
    die("failed to open %s for writing", conffile);
  fprintf(f, "%c%s\n", choice ? '+' : '-', procname);
  fclose(f);
}

static enum
{
  SWITCH_DEFAULT_ASK, SWITCH_DEFAULT_NO, SWITCH_DEFAULT_YES
} switch_default;

static bool need_switch(pid_t pid)
{
  char pathbuf[32];
  snprintf(pathbuf, 32, "/proc/%d/status", pid);
  int fd = open(pathbuf, O_RDONLY);
  char namebuf[32];
  read(fd, namebuf, 32);
  close(fd);
  *strchr(namebuf, '\n') = 0;
  char *procname = namebuf + 6;
  bool switch_yes;
  if (lookup_memo(procname, switch_yes))
    return switch_yes;
  if (switch_default != SWITCH_DEFAULT_ASK)
    return switch_default == SWITCH_DEFAULT_YES;
  bool remember = false;
  switch_yes = ask_user(procname, remember);
  if (remember)
    add_memo(procname, switch_yes);
  return switch_yes;
}

static void gdk_input_cb(void *data, int sock, GdkInputCondition cond)
{
  int fd = accept(sock, 0, 0);
  int pid;
  recv(fd, &pid, sizeof(pid), 0);
  pid = need_switch(pid);
  send(fd, &pid, sizeof(pid), 0);
  close(fd);
}

int main(int argc, char *argv[])
{
  char *opt_default = NULL;
  GError *error = NULL;
  static GOptionEntry entries[] = {
    {"default", 'D', 0, G_OPTION_ARG_STRING, &opt_default, "assume default answer", ""},
    {NULL}
  };
  if (!gtk_init_with_args (&argc, &argv, NULL, entries, NULL, &error))
    die("GTK initialization failed: %s", error->message);
  if (!opt_default)
    switch_default = SWITCH_DEFAULT_ASK;
  else if (!strcmp(opt_default, "yes"))
    switch_default = SWITCH_DEFAULT_YES;
  else if (!strcmp(opt_default, "no"))
    switch_default = SWITCH_DEFAULT_NO;
  else
    die("invalid default answer: %s", opt_default);

  struct sockaddr_un addr;
  addr.sun_family = AF_UNIX;
  snprintf(addr.sun_path, sizeof(addr.sun_path), "/tmp/libgl-switcheroo-%s/socket", getenv("USER"));
  unlink(addr.sun_path);
  int sock = socket(PF_UNIX, SOCK_STREAM, 0);
  if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    die("failed to bind socket %s: %s", addr.sun_path, strerror(errno));
  listen(sock, 16);
  gdk_input_add(sock, GDK_INPUT_READ, gdk_input_cb, NULL);
  gtk_main();

  return 0;
}
<|endoftext|>


<commit_before>
#include "QtApp.hpp"
#include "QtMenu.hpp"
#include "PythonHelpers.h"
#include "PyThreading.hpp"
#include <QAction>
#include <QTextCodec>

// Dummy vars for QApplication.
// Note that the App construction is late at init. The Python code
// has already parsed all args and warned about unknown ones, etc.
// If we want to allow some Qt args, we should add some Python arg
// like "--qtargs" and pass those here.
static int dummy_argc = 1;
static char* dummy_argv[] = {(char*)"musicplayer", NULL};

QtApp::QtApp() : QApplication(dummy_argc, dummy_argv) {
	{
		QByteArray normalizedSignature = QMetaObject::normalizedSignature("genericExec(boost::function<void(void)>)");
		int methodIndex = this->metaObject()->indexOfSlot(normalizedSignature);
		assert(methodIndex >= 0);
		genericExec_method = this->metaObject()->method(methodIndex);
	}

#if QT_VERSION < 0x050000
	// This only exists in Qt4. Afaik, Qt5 uses utf8 by default.
	QTextCodec::setCodecForCStrings(QTextCodec::codecForName("utf8"));
#endif

	this->setOrganizationName("Albert Zeyer");
	this->setApplicationName("MusicPlayer");
	this->setQuitOnLastWindowClosed(false);

	connect(this, SIGNAL(aboutToQuit()), this, SLOT(handleApplicationQuit()));
}

void QtApp::handleApplicationQuit() {
	PyScopedGIL gil;

	printf("about to quit ...\n");

	PyObject* guiMod = getModule("gui"); // borrowed
	if(!guiMod) {
		printf("QtApp::handleApplicationQuit: gui module not found");
		return;
	}

	PyObject* ret = PyObject_CallMethod(guiMod, (char*)"handleApplicationQuit", NULL);
	if(!ret && PyErr_Occurred()) PyErr_Print();
	Py_XDECREF(ret);
}

void QtApp::openWindowViaMenu() {
	if(sender() == NULL) {
		printf("QtApp::openWindowViaMenu: no sender\n");
		return;
	}

	QAction* act = qobject_cast<QAction*>(sender());
	if(!act) {
		printf("QtApp::openWindowViaMenu: sender is not QAction\n");
		return;
	}
	if(act->objectName().isEmpty()) {
		printf("QtApp::openWindowViaMenu: sender name is empty\n");
		return;
	}

	openWindow(act->objectName().toStdString());
}

void QtApp::openMainWindow() {
	openWindow("Main");
}

void QtApp::openWindow(const std::string& name) {
	QWidget* win = new QWidget();
	win->setWindowTitle(QString::fromStdString(name));
	// ...

	win->show();
}

void QtApp::minimizeWindow() {
	QWidget* win = qApp->activeWindow();
	if(win) win->showMinimized();
}

void QtApp::closeWindow() {
	QWidget* win = qApp->activeWindow();
	if(win) win->close();
}

void QtApp::edit_cut() {
	QWidget* w = QApplication::focusWidget();
	//...
}

void QtApp::edit_copy() {

}

void QtApp::edit_paste() {

}

void QtApp::edit_selectAll() {

}

void QtApp::handlePlayerUpdate() {
	updateControlMenu();
}

void QtApp::playPause() {
	PyScopedGIL gil;
	PyObject* mod = getModule("State"); // borrowed
	if(!mod) return;

	PyObject* player = NULL;
	PyObject* playing = NULL;
	bool playingBool = false;

	player = attrChain(mod, "state.player");
	if(!player) goto final;

	playing = PyObject_GetAttrString(player, "playing");
	if(!playing) goto final;

	switch(PyObject_IsTrue(playing)) {
	case 1: playingBool = true; break;
	case 0: playingBool = false; break;
	default: goto final;
	}

	playingBool = !playingBool;
	PyObject_SetAttrString_retain(player, "playing", PyBool_FromLong(playingBool));

final:
	if(PyErr_Occurred()) PyErr_Print();
	Py_XDECREF(player);
	Py_XDECREF(playing);
}

void QtApp::nextSong() {
	PyScopedGIL gil;
	PyObject* mod = getModule("State"); // borrowed
	if(!mod) return;

	PyObject* player = NULL;
	PyObject* ret = NULL;

	player = attrChain(mod, "state.player");
	ret = PyObject_CallMethod(player, "nextSong", NULL);

final:
	if(PyErr_Occurred()) PyErr_Print();
	Py_XDECREF(player);
	Py_XDECREF(ret);
}

void QtApp::debug_resetPlayer() {

}
<commit_msg>cleanup<commit_after>
#include "QtApp.hpp"
#include "QtMenu.hpp"
#include "PythonHelpers.h"
#include "PyThreading.hpp"
#include <QAction>
#include <QTextCodec>

// Dummy vars for QApplication.
// Note that the App construction is late at init. The Python code
// has already parsed all args and warned about unknown ones, etc.
// If we want to allow some Qt args, we should add some Python arg
// like "--qtargs" and pass those here.
static int dummy_argc = 1;
static char* dummy_argv[] = {(char*)"musicplayer", NULL};

QtApp::QtApp() : QApplication(dummy_argc, dummy_argv) {
	{
		QByteArray normalizedSignature = QMetaObject::normalizedSignature("genericExec(boost::function<void(void)>)");
		int methodIndex = this->metaObject()->indexOfSlot(normalizedSignature);
		assert(methodIndex >= 0);
		genericExec_method = this->metaObject()->method(methodIndex);
	}

#if QT_VERSION < 0x050000
	// This only exists in Qt4. Afaik, Qt5 uses utf8 by default.
	QTextCodec::setCodecForCStrings(QTextCodec::codecForName("utf8"));
#endif

	this->setOrganizationName("Albert Zeyer");
	this->setApplicationName("MusicPlayer");
	this->setQuitOnLastWindowClosed(false);

	connect(this, SIGNAL(aboutToQuit()), this, SLOT(handleApplicationQuit()));
}

void QtApp::handleApplicationQuit() {
	PyScopedGIL gil;

	printf("about to quit ...\n");

	PyObject* guiMod = getModule("gui"); // borrowed
	if(!guiMod) {
		printf("QtApp::handleApplicationQuit: gui module not found");
		return;
	}

	PyObject* ret = PyObject_CallMethod(guiMod, (char*)"handleApplicationQuit", NULL);
	if(!ret && PyErr_Occurred()) PyErr_Print();
	Py_XDECREF(ret);
}

void QtApp::openWindowViaMenu() {
	if(sender() == NULL) {
		printf("QtApp::openWindowViaMenu: no sender\n");
		return;
	}

	QAction* act = qobject_cast<QAction*>(sender());
	if(!act) {
		printf("QtApp::openWindowViaMenu: sender is not QAction\n");
		return;
	}
	if(act->objectName().isEmpty()) {
		printf("QtApp::openWindowViaMenu: sender name is empty\n");
		return;
	}

	openWindow(act->objectName().toStdString());
}

void QtApp::openMainWindow() {
	openWindow("Main");
}

void QtApp::openWindow(const std::string& name) {
	QWidget* win = new QWidget();
	win->setWindowTitle(QString::fromStdString(name));
	// ...

	win->show();
}

void QtApp::minimizeWindow() {
	QWidget* win = qApp->activeWindow();
	if(win) win->showMinimized();
}

void QtApp::closeWindow() {
	QWidget* win = qApp->activeWindow();
	if(win) win->close();
}

void QtApp::edit_cut() {
	QWidget* w = QApplication::focusWidget();
	//...
}

void QtApp::edit_copy() {

}

void QtApp::edit_paste() {

}

void QtApp::edit_selectAll() {

}

void QtApp::handlePlayerUpdate() {
	updateControlMenu();
}

void QtApp::playPause() {
	handleModuleCommand_noReturn("State", "state.playPause", NULL);
}

void QtApp::nextSong() {
	handleModuleCommand_noReturn("State", "state.nextSong", NULL);
}

void QtApp::debug_resetPlayer() {
	handleModuleCommand_noReturn("State", "state.player.resetPlaying", NULL);
}
<|endoftext|>