<commit_before>#include "config.h"

Config* Config::getHandle() {
	static Config instance;
	return &instance;
}

void Config::setMainConfigFile(const std::string& configFileName) {
	if (confname.empty())
		confname = configFileName;
}

void Config::readConfig() {
	config = readConfig(confname, std::ifstream(confname));
	for (auto callback : notifyList)
		callback();
}

enum ConfigState { CONFIG_BLOCK, CONFIG_KEY, CONFIG_VALUE, CONFIG_VALUE_NEXT, CONFIG_VALUE_VAR, CONFIG_VALUE_STR, CONFIG_VALUE_STR_ESCAPED };
// This enum is simply an implementation detail for the configuration parser; hence it is placed here instead of the header file.

std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>> Config::readConfig(const std::string& filename, std::istream&& configData) {
	ConfigState state = CONFIG_BLOCK;
	unsigned int lineNum = 1;
	LogManager* logger = LogManager::getHandle();
	std::string blockName, key, value, valueVar;
	std::unordered_map<std::string, std::string> blockValues;
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>> localConfig;
	while (configData.good()) {
		char nextChar = configData.get();
		if (nextChar == std::istream::traits_type::eof())
			break;
		if (nextChar == '\n')
			lineNum++;
		if (state == CONFIG_BLOCK) {
			if (nextChar == '{') {
				if (blockName.empty())
					throw ConfigError (filename, lineNum, "A block without a name was opened.");
				state = CONFIG_KEY;
			} else if (nextChar == '}')
				throw ConfigError (filename, lineNum, "A closing brace could not be mached to an open block.");
			else if (nextChar == '#') {
				while (configData.good() && configData.get() != '\n') {}
				lineNum++;
			} else if (nextChar != ' ' && nextChar != '\t' && nextChar != '\r' && nextChar != '\n')
				blockName += nextChar;
		} else if (state == CONFIG_KEY) {
			if (nextChar == '#') {
				while (configData.good() && configData.get() != '\n') {}
				lineNum++;
			} else if (nextChar == '{')
				throw ConfigError (filename, lineNum, "A block was opened inside another block.");
			else if (nextChar == '}') {
				if (blockValues.empty())
					throw ConfigError (filename, lineNum, "An empty block was defined.  What was the point of that?");
				if (!key.empty() || !value.empty())
					throw ConfigError (filename, lineNum, "A key-value pair was unfinished when the block was terminated.");
				localConfig.insert(std::pair<std::string, std::unordered_map<std::string, std::string>> (blockName, blockValues));
				blockName.clear();
				blockValues.clear();
				logger->log(LOG_ALL, "config", "Block " + blockName + " read.");
				state = CONFIG_BLOCK;
			} else if (nextChar == ';')
				throw ConfigError (filename, lineNum, "A key was specified without a value.");
			else if (nextChar == '=')
				state = CONFIG_VALUE_NEXT;
			else if (nextChar != ' ' && nextChar != '\t' && nextChar != '\r' && nextChar != '\n')
				key += nextChar;
		} else if (state == CONFIG_VALUE) {
			if (nextChar == '#') {
				while (configData.good() && configData.get() != '\n') {}
				lineNum++;
			} else if (nextChar == ';') {
				blockValues.insert(std::pair<std::string, std::string> (key, value));
				key.clear();
				value.clear();
				state = CONFIG_KEY;
			} else if (nextChar == '+')
				state = CONFIG_VALUE_NEXT;
			else
				throw ConfigError (filename, lineNum, "An unexpected character was encountered; expected ';' or '+' (perhaps you forgot to end or properly concatenate your value?).");
		} else if (state == CONFIG_VALUE_NEXT) {
			if (nextChar == '#') {
				while (configData.good() && configData.get() != '\n') {}
				lineNum++;
			} else if (nextChar == '"')
				state = CONFIG_VALUE_STR;
			else if (nextChar != ' ' && nextChar != '\t' && nextChar != '\r' && nextChar != '\n') {
				valueVar += nextChar;
				state = CONFIG_VALUE_VAR;
			}
		} else if (state == CONFIG_VALUE_VAR) {
			if (nextChar == '"')
				throw ConfigError (filename, lineNum, "A string value was specified in the middle of a variable (perhaps you forgot to properly concatenate with '+'?).");
			else if (nextChar == '{')
				throw ConfigError (filename, lineNum, "A block was opened inside another block.");
			else if (nextChar == '}')
				throw ConfigError (filename, lineNum, "A key-value pair was unfinished when the block was terminated.");
			else if (nextChar == ' ' || nextChar == '\t' || nextChar == '\r' || nextChar == '\n' || nextChar == '+' || nextChar == ';') {
				auto keyIter = blockValues.find(valueVar);
				if (keyIter == blockValues.end())
					throw ConfigError (filename, lineNum, "The variable " + valueVar + " was specified, but did not match a variable already specified in the block.");
				value += keyIter->second;
				valueVar.clear();
				if (nextChar == ';') {
					state = CONFIG_KEY;
					blockValues.insert(std::pair<std::string, std::string> (key, value));
					key.clear();
					value.clear();
				} else if (nextChar == '+')
					state = CONFIG_VALUE_NEXT;
				else
					state = CONFIG_VALUE;
			} else
				valueVar += nextChar;
		} else if (state == CONFIG_VALUE_STR) {
			if (nextChar == '\\')
				state = CONFIG_VALUE_STR_ESCAPED;
			else if (nextChar == '"')
				state = CONFIG_VALUE;
			else
				value += nextChar;
		} else if (state == CONFIG_VALUE_STR_ESCAPED) {
			if (nextChar == '\\')
				value += '\\';
			else if (nextChar == 'n')
				value += '\n';
			else if (nextChar == 't')
				value += '\t';
			else if (nextChar == 'r')
				value += '\r';
			else
				value += nextChar;
			state = CONFIG_VALUE_STR;
		}
	}
	if (!blockValues.empty())
		throw ConfigError (filename, lineNum, "A block remained unterminated at the end of the file.");
	std::list<std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>> includedConfigs;
	for (auto block : localConfig) {
		if (block.first == "include") {
			auto inclfIter = block.second.find("file");
			if (inclfIter != block.second.end()) {
				std::string name = inclfIter->second;
				logger->log(LOG_ALL, "config", "Reading included file " + inclfIter->second);
				includedConfigs.push_back(readConfig(inclfIter->second, std::ifstream(name)));
			} else {
				auto incleIter = block.second.find("executable");
				if (incleIter != block.second.end()) {
					std::string cmd = incleIter->second;
					logger->log(LOG_ALL, "config", "Getting configuration data from `" + incleIter->second + "`");
					FILE* pipe = popen(cmd.c_str(), "r");
					if (!pipe)
						throw ConfigError (cmd, 0, "Could not open pipe to read output.");
					char buffer[256];
					std::stringstream output;
					while (!feof(pipe)) {
						if (fgets(buffer, 256, pipe) != NULL)
							output << buffer;
					}
					pclose(pipe);
					includedConfigs.push_back(readConfig(cmd, output));
				} else
					throw ConfigError (filename, lineNum, "An include block was present that contained neither a file nor an executable.");
			}
		}
	}
	for (auto includes : includedConfigs) {
		for (auto conf : includes) {
			for (auto block : conf)
				localConfig.insert(std::pair<std::string, std::unordered_map<std::string, std::string>> (block));
		}
	}
	return localConfig;
}

void Config::addRehashNotify(std::function<void()> notifyCallback) {
	notifyList.push_back(notifyCallback);
}

size_t Config::blockCount(const std::string& block) const {
	return config.count(block);
}

std::list<std::unordered_map<std::string, std::string>> Config::getBlock(const std::string& block) const {
	std::list<std::unordered_map<std::string, std::string>> blockList;
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (; startIter != endIter; ++startIter)
		blockList.push_back(startIter->second);
	return blockList;
}

std::unordered_map<std::string, std::string> Config::getSingleBlock(const std::string& block, const std::unordered_map<std::string, std::string>& conditions) const {
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (; startIter != endIter; ++startIter) {
		for (auto check : conditions) {
			auto blockIter = startIter->second.find(check.first);
			if (blockIter == startIter->second.end())
				continue;
			if (check.second == blockIter->second)
				return startIter->second;
		}
	}
	return std::unordered_map<std::string, std::string> ();
}

std::string Config::getValue(const std::string& block, const std::string& key) const {
	auto blockIter = config.find(block);
	if (blockIter == config.end())
		return "";
	auto dataIter = blockIter->second.find(key);
	if (dataIter == blockIter->second.end())
		return "";
	return dataIter->second;
}

bool Config::getBoolValue(const std::string& block, const std::string& key) const {
	const std::string& value = getValue(block, key);
	std::string lowerValue;
	std::transform(value.begin(), value.end(), std::back_inserter(lowerValue), ::tolower);
	if (lowerValue == "yes" || lowerValue == "on" || lowerValue == "true")
		return true;
	return false;
}

std::list<std::string> Config::getAllValues(const std::string& block, const std::string& key) const {
	std::list<std::string> valueList;
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (; startIter != endIter; ++startIter) {
		auto dataIter = startIter->second.find(key);
		if (dataIter == startIter->second.end())
			valueList.push_back("");
		else
			valueList.push_back(dataIter->second);
	}
	return valueList;
}

std::list<bool> Config::getAllBoolValues(const std::string& block, const std::string& key) const {
	std::list<bool> valueList;
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (std::string lowerValue; startIter != endIter; ++startIter) {
		auto dataIter = startIter->second.find(key);
		if (dataIter == startIter->second.end())
			valueList.push_back(false);
		else {
			lowerValue.clear();
			std::transform(dataIter->second.begin(), dataIter->second.end(), std::back_inserter(lowerValue), ::tolower);
			if (lowerValue == "yes" || lowerValue == "on" || lowerValue == "true")
				valueList.push_back(true);
			else
				valueList.push_back(false);
		}
	}
	return valueList;
}

static bool Config::makeBool(const std::string& value) {
	std::string lowerValue;
	std::transform(value.begin(), value.end(), std::back_inserter(lowerValue), ::tolower);
	if (lowerValue == "yes" || lowerValue == "on" || lowerValue == "true")
		return true;
	return false;
}

Config::Config() {}

ConfigError::ConfigError(const std::string& filename, unsigned int lineNum, const std::string& description) {
	std::ostringstream descStr;
	descStr << "An error occurred reading the configuration from '" << filename << "' on line " << lineNum << ": " << description;
	desc = descStr.str();
}<commit_msg>Manually expand the resulting pair<commit_after>#include "config.h"

Config* Config::getHandle() {
	static Config instance;
	return &instance;
}

void Config::setMainConfigFile(const std::string& configFileName) {
	if (confname.empty())
		confname = configFileName;
}

void Config::readConfig() {
	config = readConfig(confname, std::ifstream(confname));
	for (auto callback : notifyList)
		callback();
}

enum ConfigState { CONFIG_BLOCK, CONFIG_KEY, CONFIG_VALUE, CONFIG_VALUE_NEXT, CONFIG_VALUE_VAR, CONFIG_VALUE_STR, CONFIG_VALUE_STR_ESCAPED };
// This enum is simply an implementation detail for the configuration parser; hence it is placed here instead of the header file.

std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>> Config::readConfig(const std::string& filename, std::istream&& configData) {
	ConfigState state = CONFIG_BLOCK;
	unsigned int lineNum = 1;
	LogManager* logger = LogManager::getHandle();
	std::string blockName, key, value, valueVar;
	std::unordered_map<std::string, std::string> blockValues;
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>> localConfig;
	while (configData.good()) {
		char nextChar = configData.get();
		if (nextChar == std::istream::traits_type::eof())
			break;
		if (nextChar == '\n')
			lineNum++;
		if (state == CONFIG_BLOCK) {
			if (nextChar == '{') {
				if (blockName.empty())
					throw ConfigError (filename, lineNum, "A block without a name was opened.");
				state = CONFIG_KEY;
			} else if (nextChar == '}')
				throw ConfigError (filename, lineNum, "A closing brace could not be mached to an open block.");
			else if (nextChar == '#') {
				while (configData.good() && configData.get() != '\n') {}
				lineNum++;
			} else if (nextChar != ' ' && nextChar != '\t' && nextChar != '\r' && nextChar != '\n')
				blockName += nextChar;
		} else if (state == CONFIG_KEY) {
			if (nextChar == '#') {
				while (configData.good() && configData.get() != '\n') {}
				lineNum++;
			} else if (nextChar == '{')
				throw ConfigError (filename, lineNum, "A block was opened inside another block.");
			else if (nextChar == '}') {
				if (blockValues.empty())
					throw ConfigError (filename, lineNum, "An empty block was defined.  What was the point of that?");
				if (!key.empty() || !value.empty())
					throw ConfigError (filename, lineNum, "A key-value pair was unfinished when the block was terminated.");
				localConfig.insert(std::pair<std::string, std::unordered_map<std::string, std::string>> (blockName, blockValues));
				blockName.clear();
				blockValues.clear();
				logger->log(LOG_ALL, "config", "Block " + blockName + " read.");
				state = CONFIG_BLOCK;
			} else if (nextChar == ';')
				throw ConfigError (filename, lineNum, "A key was specified without a value.");
			else if (nextChar == '=')
				state = CONFIG_VALUE_NEXT;
			else if (nextChar != ' ' && nextChar != '\t' && nextChar != '\r' && nextChar != '\n')
				key += nextChar;
		} else if (state == CONFIG_VALUE) {
			if (nextChar == '#') {
				while (configData.good() && configData.get() != '\n') {}
				lineNum++;
			} else if (nextChar == ';') {
				blockValues.insert(std::pair<std::string, std::string> (key, value));
				key.clear();
				value.clear();
				state = CONFIG_KEY;
			} else if (nextChar == '+')
				state = CONFIG_VALUE_NEXT;
			else
				throw ConfigError (filename, lineNum, "An unexpected character was encountered; expected ';' or '+' (perhaps you forgot to end or properly concatenate your value?).");
		} else if (state == CONFIG_VALUE_NEXT) {
			if (nextChar == '#') {
				while (configData.good() && configData.get() != '\n') {}
				lineNum++;
			} else if (nextChar == '"')
				state = CONFIG_VALUE_STR;
			else if (nextChar != ' ' && nextChar != '\t' && nextChar != '\r' && nextChar != '\n') {
				valueVar += nextChar;
				state = CONFIG_VALUE_VAR;
			}
		} else if (state == CONFIG_VALUE_VAR) {
			if (nextChar == '"')
				throw ConfigError (filename, lineNum, "A string value was specified in the middle of a variable (perhaps you forgot to properly concatenate with '+'?).");
			else if (nextChar == '{')
				throw ConfigError (filename, lineNum, "A block was opened inside another block.");
			else if (nextChar == '}')
				throw ConfigError (filename, lineNum, "A key-value pair was unfinished when the block was terminated.");
			else if (nextChar == ' ' || nextChar == '\t' || nextChar == '\r' || nextChar == '\n' || nextChar == '+' || nextChar == ';') {
				auto keyIter = blockValues.find(valueVar);
				if (keyIter == blockValues.end())
					throw ConfigError (filename, lineNum, "The variable " + valueVar + " was specified, but did not match a variable already specified in the block.");
				value += keyIter->second;
				valueVar.clear();
				if (nextChar == ';') {
					state = CONFIG_KEY;
					blockValues.insert(std::pair<std::string, std::string> (key, value));
					key.clear();
					value.clear();
				} else if (nextChar == '+')
					state = CONFIG_VALUE_NEXT;
				else
					state = CONFIG_VALUE;
			} else
				valueVar += nextChar;
		} else if (state == CONFIG_VALUE_STR) {
			if (nextChar == '\\')
				state = CONFIG_VALUE_STR_ESCAPED;
			else if (nextChar == '"')
				state = CONFIG_VALUE;
			else
				value += nextChar;
		} else if (state == CONFIG_VALUE_STR_ESCAPED) {
			if (nextChar == '\\')
				value += '\\';
			else if (nextChar == 'n')
				value += '\n';
			else if (nextChar == 't')
				value += '\t';
			else if (nextChar == 'r')
				value += '\r';
			else
				value += nextChar;
			state = CONFIG_VALUE_STR;
		}
	}
	if (!blockValues.empty())
		throw ConfigError (filename, lineNum, "A block remained unterminated at the end of the file.");
	std::list<std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>> includedConfigs;
	for (auto block : localConfig) {
		if (block.first == "include") {
			auto inclfIter = block.second.find("file");
			if (inclfIter != block.second.end()) {
				std::string name = inclfIter->second;
				logger->log(LOG_ALL, "config", "Reading included file " + inclfIter->second);
				includedConfigs.push_back(readConfig(inclfIter->second, std::ifstream(name)));
			} else {
				auto incleIter = block.second.find("executable");
				if (incleIter != block.second.end()) {
					std::string cmd = incleIter->second;
					logger->log(LOG_ALL, "config", "Getting configuration data from `" + incleIter->second + "`");
					FILE* pipe = popen(cmd.c_str(), "r");
					if (!pipe)
						throw ConfigError (cmd, 0, "Could not open pipe to read output.");
					char buffer[256];
					std::stringstream output;
					while (!feof(pipe)) {
						if (fgets(buffer, 256, pipe) != NULL)
							output << buffer;
					}
					pclose(pipe);
					includedConfigs.push_back(readConfig(cmd, output));
				} else
					throw ConfigError (filename, lineNum, "An include block was present that contained neither a file nor an executable.");
			}
		}
	}
	for (auto includes : includedConfigs) {
		for (auto conf : includes) {
			for (auto block : conf)
				localConfig.insert(std::pair<std::string, std::unordered_map<std::string, std::string>> (block.first, block.second));
		}
	}
	return localConfig;
}

void Config::addRehashNotify(std::function<void()> notifyCallback) {
	notifyList.push_back(notifyCallback);
}

size_t Config::blockCount(const std::string& block) const {
	return config.count(block);
}

std::list<std::unordered_map<std::string, std::string>> Config::getBlock(const std::string& block) const {
	std::list<std::unordered_map<std::string, std::string>> blockList;
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (; startIter != endIter; ++startIter)
		blockList.push_back(startIter->second);
	return blockList;
}

std::unordered_map<std::string, std::string> Config::getSingleBlock(const std::string& block, const std::unordered_map<std::string, std::string>& conditions) const {
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (; startIter != endIter; ++startIter) {
		for (auto check : conditions) {
			auto blockIter = startIter->second.find(check.first);
			if (blockIter == startIter->second.end())
				continue;
			if (check.second == blockIter->second)
				return startIter->second;
		}
	}
	return std::unordered_map<std::string, std::string> ();
}

std::string Config::getValue(const std::string& block, const std::string& key) const {
	auto blockIter = config.find(block);
	if (blockIter == config.end())
		return "";
	auto dataIter = blockIter->second.find(key);
	if (dataIter == blockIter->second.end())
		return "";
	return dataIter->second;
}

bool Config::getBoolValue(const std::string& block, const std::string& key) const {
	const std::string& value = getValue(block, key);
	std::string lowerValue;
	std::transform(value.begin(), value.end(), std::back_inserter(lowerValue), ::tolower);
	if (lowerValue == "yes" || lowerValue == "on" || lowerValue == "true")
		return true;
	return false;
}

std::list<std::string> Config::getAllValues(const std::string& block, const std::string& key) const {
	std::list<std::string> valueList;
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (; startIter != endIter; ++startIter) {
		auto dataIter = startIter->second.find(key);
		if (dataIter == startIter->second.end())
			valueList.push_back("");
		else
			valueList.push_back(dataIter->second);
	}
	return valueList;
}

std::list<bool> Config::getAllBoolValues(const std::string& block, const std::string& key) const {
	std::list<bool> valueList;
	std::unordered_multimap<std::string, std::unordered_map<std::string, std::string>>::const_iterator startIter, endIter;
	std::tie(startIter, endIter) = config.equal_range(block);
	for (std::string lowerValue; startIter != endIter; ++startIter) {
		auto dataIter = startIter->second.find(key);
		if (dataIter == startIter->second.end())
			valueList.push_back(false);
		else {
			lowerValue.clear();
			std::transform(dataIter->second.begin(), dataIter->second.end(), std::back_inserter(lowerValue), ::tolower);
			if (lowerValue == "yes" || lowerValue == "on" || lowerValue == "true")
				valueList.push_back(true);
			else
				valueList.push_back(false);
		}
	}
	return valueList;
}

static bool Config::makeBool(const std::string& value) {
	std::string lowerValue;
	std::transform(value.begin(), value.end(), std::back_inserter(lowerValue), ::tolower);
	if (lowerValue == "yes" || lowerValue == "on" || lowerValue == "true")
		return true;
	return false;
}

Config::Config() {}

ConfigError::ConfigError(const std::string& filename, unsigned int lineNum, const std::string& description) {
	std::ostringstream descStr;
	descStr << "An error occurred reading the configuration from '" << filename << "' on line " << lineNum << ": " << description;
	desc = descStr.str();
}<|endoftext|>


<commit_before>#include <wx/fileconf.h>

#include "config.h"

Config appConfig;

Config::Config() {
}

Config::~Config() {
}

// FIXME - i hate to use this
// This is a macro that will allocate and deallocate the wxConfig, since
// our app crashes if we let it live too long (for some reason). This
// is a temporary hack, which should be fixed ASAP.
#define CFG_OP(cfg,op) \
	wxFileConfig* cfg = new wxFileConfig(_T("bzlauncher")); \
	{ op } while(0); \
	delete cfg; \
	cfg = NULL;

wxString Config::getBZFlagCommand(const wxString& proto) const {
	// first try bzflag/proto (eg bzflag/bzfs0026)
	// then try bzflag/default
	wxString key = wxString::Format(_T("bzflag/%s"), proto.Lower().c_str());
	wxString cmd;

	CFG_OP(cfg,
		if(! cfg->Read(key, &cmd)) {
			if(! cfg->Read(_T("bzflag/default"), &cmd)) {
				return _T("");
			}
		}
	);

	return cmd;
}

void Config::setBZFlagCommand(const wxString& cmd, const wxString& proto) {
	CFG_OP(cfg, cfg->Write(wxString::Format(_T("bzflag/%s"), proto.c_str()), cmd););
}

int Config::getSortMode() const {
	int mode;
	CFG_OP(cfg, mode = cfg->Read(_T("window/sortmode"), -4); );
	return mode;
}

void Config::setSortMode(int s) {
	CFG_OP(cfg, cfg->Write(_T("window/sortmode"), s); );
}

wxRect Config::getWindowDimensions() const {
	wxRect wanted;

	CFG_OP(cfg,
		wanted.x      = cfg->Read(_T("window/x"), 10);
		wanted.y      = cfg->Read(_T("window/y"), 10);
		wanted.width  = cfg->Read(_T("window/w"), 600);
		wanted.height = cfg->Read(_T("window/h"), 600);
	);
	return wanted;
}

void Config::setWindowDimensions(wxRect r) {
	CFG_OP(cfg,
		cfg->Write(_T("window/x"), r.x);
		cfg->Write(_T("window/y"), r.y);
		cfg->Write(_T("window/h"), r.height);
		cfg->Write(_T("window/w"), r.width);
	);
}

wxString Config::getColumnName(ColType t) const {
	static const wxString names [] = {
		_T("server"),
		_T("name"),
		_T("type"),
		_T("players"),
		_T("ping"),
		_T("favorite")
	};

	return names[t];
}

wxString Config::getColumnKey(ColType type) const {
	wxString key;
	key += _T("window/col_");
	key += this->getColumnName(type);
	key += _T("_width");
	return key;
}

int Config::getColumnDefaultWidth(ColType t) const {
	const int widths[] = {
		157,
		300,
		47,
		30,
		46,
		46
	};

	return widths[t];
}

int Config::getColumnWidth(ColType type) const {
	int w;
	wxString key = this->getColumnKey(type);
	CFG_OP(cfg,
		w = cfg->Read(key, this->getColumnDefaultWidth(type));
	);
	return w;
}

void Config::setColumnWidth(ColType type, int w) {
	wxString key = this->getColumnKey(type);
	CFG_OP(cfg, cfg->Write(key,w););
}

wxArrayString Config::getFavorites() const {
	wxString      str;
	wxArrayString list;
	int           count = 0;

	CFG_OP(cfg,
		while(cfg->Read(wxString::Format(_T("favorites/%d"), count), &str)) {
			list.Add(str);
			count++;
		}
	);

	return list;
}

void Config::setFavorites(const wxArrayString& list) {
	CFG_OP(cfg,
		for(unsigned int i = 0; i < list.GetCount(); i++)
			cfg->Write(wxString::Format(_T("favorites/%d"), i), list.Item(i));
	);
}

wxString Config::getListServerURL(int n) const {
	int count = 0;
	wxString str;
	CFG_OP(cfg,
		while(cfg->Read(wxString::Format(_T("listserver/%d"), count), &str)) {
			if(count == n) return str;
			count++;
		}
	);

	if(count == 0 && n == 1)
		return _T("http://my.bzflag.org/db?action=LIST");
	else
		return _T("http://bzstats.strayer.de/stuff/listserver.php?protocol=NEW");
}
<commit_msg>Changed the URL for strayers listserver<commit_after>#include <wx/fileconf.h>

#include "config.h"

Config appConfig;

Config::Config() {
}

Config::~Config() {
}

// FIXME - i hate to use this
// This is a macro that will allocate and deallocate the wxConfig, since
// our app crashes if we let it live too long (for some reason). This
// is a temporary hack, which should be fixed ASAP.
#define CFG_OP(cfg,op) \
	wxFileConfig* cfg = new wxFileConfig(_T("bzlauncher")); \
	{ op } while(0); \
	delete cfg; \
	cfg = NULL;

wxString Config::getBZFlagCommand(const wxString& proto) const {
	// first try bzflag/proto (eg bzflag/bzfs0026)
	// then try bzflag/default
	wxString key = wxString::Format(_T("bzflag/%s"), proto.Lower().c_str());
	wxString cmd;

	CFG_OP(cfg,
		if(! cfg->Read(key, &cmd)) {
			if(! cfg->Read(_T("bzflag/default"), &cmd)) {
				return _T("");
			}
		}
	);

	return cmd;
}

void Config::setBZFlagCommand(const wxString& cmd, const wxString& proto) {
	CFG_OP(cfg, cfg->Write(wxString::Format(_T("bzflag/%s"), proto.c_str()), cmd););
}

int Config::getSortMode() const {
	int mode;
	CFG_OP(cfg, mode = cfg->Read(_T("window/sortmode"), -4); );
	return mode;
}

void Config::setSortMode(int s) {
	CFG_OP(cfg, cfg->Write(_T("window/sortmode"), s); );
}

wxRect Config::getWindowDimensions() const {
	wxRect wanted;

	CFG_OP(cfg,
		wanted.x      = cfg->Read(_T("window/x"), 10);
		wanted.y      = cfg->Read(_T("window/y"), 10);
		wanted.width  = cfg->Read(_T("window/w"), 600);
		wanted.height = cfg->Read(_T("window/h"), 600);
	);
	return wanted;
}

void Config::setWindowDimensions(wxRect r) {
	CFG_OP(cfg,
		cfg->Write(_T("window/x"), r.x);
		cfg->Write(_T("window/y"), r.y);
		cfg->Write(_T("window/h"), r.height);
		cfg->Write(_T("window/w"), r.width);
	);
}

wxString Config::getColumnName(ColType t) const {
	static const wxString names [] = {
		_T("server"),
		_T("name"),
		_T("type"),
		_T("players"),
		_T("ping"),
		_T("favorite")
	};

	return names[t];
}

wxString Config::getColumnKey(ColType type) const {
	wxString key;
	key += _T("window/col_");
	key += this->getColumnName(type);
	key += _T("_width");
	return key;
}

int Config::getColumnDefaultWidth(ColType t) const {
	const int widths[] = {
		157,
		300,
		47,
		30,
		46,
		46
	};

	return widths[t];
}

int Config::getColumnWidth(ColType type) const {
	int w;
	wxString key = this->getColumnKey(type);
	CFG_OP(cfg,
		w = cfg->Read(key, this->getColumnDefaultWidth(type));
	);
	return w;
}

void Config::setColumnWidth(ColType type, int w) {
	wxString key = this->getColumnKey(type);
	CFG_OP(cfg, cfg->Write(key,w););
}

wxArrayString Config::getFavorites() const {
	wxString      str;
	wxArrayString list;
	int           count = 0;

	CFG_OP(cfg,
		while(cfg->Read(wxString::Format(_T("favorites/%d"), count), &str)) {
			list.Add(str);
			count++;
		}
	);

	return list;
}

void Config::setFavorites(const wxArrayString& list) {
	CFG_OP(cfg,
		for(unsigned int i = 0; i < list.GetCount(); i++)
			cfg->Write(wxString::Format(_T("favorites/%d"), i), list.Item(i));
	);
}

wxString Config::getListServerURL(int n) const {
	int count = 0;
	wxString str;
	CFG_OP(cfg,
		while(cfg->Read(wxString::Format(_T("listserver/%d"), count), &str)) {
			if(count == n) return str;
			count++;
		}
	);

	if(count == 0 && n == 1)
		return _T("http://my.bzflag.org/db?action=LIST");
	else
		return _T("http://bzstats.strayer.de/stuff/listserver.php");
}
<|endoftext|>


<commit_before>#include "context.hh"

#include "alias_registry.hh"
#include "client.hh"
#include "user_interface.hh"
#include "register_manager.hh"
#include "window.hh"

namespace Kakoune
{

Context::~Context() = default;

Context::Context(InputHandler& input_handler, SelectionList selections,
                 Flags flags, String name)
    : m_input_handler{&input_handler},
      m_selections{std::move(selections)},
      m_flags(flags),
      m_name(std::move(name))
{}

Context::Context(EmptyContextFlag) {}

Buffer& Context::buffer() const
{
    if (not has_buffer())
        throw runtime_error("no buffer in context");
    return const_cast<Buffer&>((*m_selections).buffer());
}

Window& Context::window() const
{
    if (not has_window())
        throw runtime_error("no window in context");
    return *m_window;
}

InputHandler& Context::input_handler() const
{
    if (not has_input_handler())
        throw runtime_error("no input handler in context");
    return *m_input_handler;
}

Client& Context::client() const
{
    if (not has_client())
        throw runtime_error("no client in context");
    return *m_client;
}

UserInterface& Context::ui() const
{
    if (not has_ui())
        throw runtime_error("no user interface in context");
    return client().ui();
}

Scope& Context::scope() const
{
    if (has_window())
        return window();
    if (has_buffer())
        return buffer();
    return GlobalScope::instance();
}

void Context::set_client(Client& client)
{
    kak_assert(not has_client());
    m_client.reset(&client);
}

void Context::set_window(Window& window)
{
    kak_assert(&window.buffer() == &buffer());
    m_window.reset(&window);
}

void Context::print_status(DisplayLine status) const
{
    if (has_client())
        client().print_status(std::move(status));
}

void Context::push_jump()
{
    const SelectionList& jump = selections();
    if (m_current_jump != m_jump_list.end())
    {
        auto begin = m_current_jump;
        if (&buffer() != &begin->buffer() or *begin != jump)
            ++begin;
        m_jump_list.erase(begin, m_jump_list.end());
    }
    m_jump_list.erase(std::remove(begin(m_jump_list), end(m_jump_list), jump),
                      end(m_jump_list));
    m_jump_list.push_back(jump);
    m_current_jump = m_jump_list.end();
}

void Context::drop_jump()
{
    if (not m_jump_list.empty())
        m_jump_list.pop_back();
    m_current_jump = m_jump_list.end();
}

const SelectionList& Context::jump_forward()
{
    if (m_current_jump != m_jump_list.end() and
        m_current_jump + 1 != m_jump_list.end())
    {
        SelectionList& res = *++m_current_jump;
        res.update();
        return res;
    }
    throw runtime_error("no next jump");
}

const SelectionList& Context::jump_backward()
{
    if (m_current_jump != m_jump_list.end() and
        *m_current_jump != selections())
    {
        push_jump();
        SelectionList& res = *--m_current_jump;
        res.update();
        return res;
    }
    if (m_current_jump != m_jump_list.begin())
    {
        if (m_current_jump == m_jump_list.end())
        {
            push_jump();
            --m_current_jump;
            if (m_current_jump == m_jump_list.begin())
                throw runtime_error("no previous jump");
        }
        SelectionList& res = *--m_current_jump;
        res.update();
        return res;
    }
    throw runtime_error("no previous jump");
}

void Context::forget_jumps_to_buffer(Buffer& buffer)
{
    for (auto it = m_jump_list.begin(); it != m_jump_list.end();)
    {
        if (&it->buffer() == &buffer)
        {
            if (it < m_current_jump)
                --m_current_jump;
            else if (it == m_current_jump)
                m_current_jump = m_jump_list.end()-1;

            it = m_jump_list.erase(it);
        }
        else
            ++it;
    }
}

void Context::change_buffer(Buffer& buffer)
{
    if (&buffer == &this->buffer())
        return;

    if (m_edition_level > 0)
       this->buffer().commit_undo_group();

    m_window.reset();
    if (has_client())
        client().change_buffer(buffer);
    else
        m_selections = SelectionList{buffer, Selection{}};
    if (has_input_handler())
        input_handler().reset_normal_mode();
}

SelectionList& Context::selections()
{
    if (not m_selections)
        throw runtime_error("no selections in context");
    (*m_selections).update();
    return *m_selections;
}

SelectionList& Context::selections_write_only()
{
    if (not m_selections)
        throw runtime_error("no selections in context");
    return *m_selections;
}

const SelectionList& Context::selections() const
{
    return const_cast<Context&>(*this).selections();
}

Vector<String> Context::selections_content() const
{
    auto& buf = buffer();
    Vector<String> contents;
    for (auto& sel : selections())
        contents.push_back(buf.string(sel.min(), buf.char_next(sel.max())));
    return contents;
}

void Context::begin_edition()
{
    if (m_edition_level >= 0)
        ++m_edition_level;
}

void Context::end_edition()
{
    if (m_edition_level < 0)
        return;

    kak_assert(m_edition_level != 0);
    if (m_edition_level == 1)
        buffer().commit_undo_group();

    --m_edition_level;
}

StringView Context::main_sel_register_value(StringView reg) const
{
    auto strings = RegisterManager::instance()[reg].values(*this);
    size_t index = m_selections ? (*m_selections).main_index() : 0;
    if (strings.size() <= index)
        index = strings.size() - 1;
   return strings[index];
}

}
<commit_msg>Tweak Context::push_jump implementation, simplify code<commit_after>#include "context.hh"

#include "alias_registry.hh"
#include "client.hh"
#include "user_interface.hh"
#include "register_manager.hh"
#include "window.hh"

namespace Kakoune
{

Context::~Context() = default;

Context::Context(InputHandler& input_handler, SelectionList selections,
                 Flags flags, String name)
    : m_input_handler{&input_handler},
      m_selections{std::move(selections)},
      m_flags(flags),
      m_name(std::move(name))
{}

Context::Context(EmptyContextFlag) {}

Buffer& Context::buffer() const
{
    if (not has_buffer())
        throw runtime_error("no buffer in context");
    return const_cast<Buffer&>((*m_selections).buffer());
}

Window& Context::window() const
{
    if (not has_window())
        throw runtime_error("no window in context");
    return *m_window;
}

InputHandler& Context::input_handler() const
{
    if (not has_input_handler())
        throw runtime_error("no input handler in context");
    return *m_input_handler;
}

Client& Context::client() const
{
    if (not has_client())
        throw runtime_error("no client in context");
    return *m_client;
}

UserInterface& Context::ui() const
{
    if (not has_ui())
        throw runtime_error("no user interface in context");
    return client().ui();
}

Scope& Context::scope() const
{
    if (has_window())
        return window();
    if (has_buffer())
        return buffer();
    return GlobalScope::instance();
}

void Context::set_client(Client& client)
{
    kak_assert(not has_client());
    m_client.reset(&client);
}

void Context::set_window(Window& window)
{
    kak_assert(&window.buffer() == &buffer());
    m_window.reset(&window);
}

void Context::print_status(DisplayLine status) const
{
    if (has_client())
        client().print_status(std::move(status));
}

void Context::push_jump()
{
    const SelectionList& jump = selections();
    if (m_current_jump != m_jump_list.end())
        m_jump_list.erase(m_current_jump+1, m_jump_list.end());
    m_jump_list.erase(std::remove(begin(m_jump_list), end(m_jump_list), jump),
                      end(m_jump_list));
    m_jump_list.push_back(jump);
    m_current_jump = m_jump_list.end();
}

void Context::drop_jump()
{
    if (not m_jump_list.empty())
        m_jump_list.pop_back();
    m_current_jump = m_jump_list.end();
}

const SelectionList& Context::jump_forward()
{
    if (m_current_jump != m_jump_list.end() and
        m_current_jump + 1 != m_jump_list.end())
    {
        SelectionList& res = *++m_current_jump;
        res.update();
        return res;
    }
    throw runtime_error("no next jump");
}

const SelectionList& Context::jump_backward()
{
    if (m_current_jump != m_jump_list.end() and
        *m_current_jump != selections())
    {
        push_jump();
        SelectionList& res = *--m_current_jump;
        res.update();
        return res;
    }
    if (m_current_jump != m_jump_list.begin())
    {
        if (m_current_jump == m_jump_list.end())
        {
            push_jump();
            --m_current_jump;
            if (m_current_jump == m_jump_list.begin())
                throw runtime_error("no previous jump");
        }
        SelectionList& res = *--m_current_jump;
        res.update();
        return res;
    }
    throw runtime_error("no previous jump");
}

void Context::forget_jumps_to_buffer(Buffer& buffer)
{
    for (auto it = m_jump_list.begin(); it != m_jump_list.end();)
    {
        if (&it->buffer() == &buffer)
        {
            if (it < m_current_jump)
                --m_current_jump;
            else if (it == m_current_jump)
                m_current_jump = m_jump_list.end()-1;

            it = m_jump_list.erase(it);
        }
        else
            ++it;
    }
}

void Context::change_buffer(Buffer& buffer)
{
    if (&buffer == &this->buffer())
        return;

    if (m_edition_level > 0)
       this->buffer().commit_undo_group();

    m_window.reset();
    if (has_client())
        client().change_buffer(buffer);
    else
        m_selections = SelectionList{buffer, Selection{}};
    if (has_input_handler())
        input_handler().reset_normal_mode();
}

SelectionList& Context::selections()
{
    if (not m_selections)
        throw runtime_error("no selections in context");
    (*m_selections).update();
    return *m_selections;
}

SelectionList& Context::selections_write_only()
{
    if (not m_selections)
        throw runtime_error("no selections in context");
    return *m_selections;
}

const SelectionList& Context::selections() const
{
    return const_cast<Context&>(*this).selections();
}

Vector<String> Context::selections_content() const
{
    auto& buf = buffer();
    Vector<String> contents;
    for (auto& sel : selections())
        contents.push_back(buf.string(sel.min(), buf.char_next(sel.max())));
    return contents;
}

void Context::begin_edition()
{
    if (m_edition_level >= 0)
        ++m_edition_level;
}

void Context::end_edition()
{
    if (m_edition_level < 0)
        return;

    kak_assert(m_edition_level != 0);
    if (m_edition_level == 1)
        buffer().commit_undo_group();

    --m_edition_level;
}

StringView Context::main_sel_register_value(StringView reg) const
{
    auto strings = RegisterManager::instance()[reg].values(*this);
    size_t index = m_selections ? (*m_selections).main_index() : 0;
    if (strings.size() <= index)
        index = strings.size() - 1;
   return strings[index];
}

}
<|endoftext|>


<commit_before>#ifndef context_hh_INCLUDED
#define context_hh_INCLUDED

#include "window.hh"

namespace Kakoune
{

class Buffer;

struct Context
{
    Context()
        : m_window(nullptr), m_buffer(nullptr) {}
    Context(Window& window)
        : m_window(&window), m_buffer(&window.buffer()) {}
    Context(Buffer& buffer)
        : m_window(nullptr), m_buffer(&buffer) {}

    Buffer& buffer() const
    {
        if (not m_buffer)
            throw runtime_error("no buffer in context");
        return *m_buffer;
    }
    bool has_buffer() const { return m_buffer; }

    Window& window() const
    {
        if (not m_window)
            throw runtime_error("no window in context");
        return *m_window;
    }
    bool has_window() const { return m_window; }

    OptionManager& option_manager() const
    {
        if (m_window)
            return m_window->option_manager();
        if (m_buffer)
            return m_buffer->option_manager();
        return GlobalOptionManager::instance();
    }

    int numeric_param() const { return m_numeric_param; }
    void numeric_param(int param) { m_numeric_param = param; }

public:
    safe_ptr<Window> m_window;
    safe_ptr<Buffer> m_buffer;

    int m_numeric_param = 0;
};

}
#endif // context_hh_INCLUDED
<commit_msg>Context: store an editor instead of a window<commit_after>#ifndef context_hh_INCLUDED
#define context_hh_INCLUDED

#include "window.hh"

namespace Kakoune
{

class Buffer;

struct Context
{
    Context() {}
    Context(Editor& editor)
        : m_editor(&editor), m_buffer(&editor.buffer()) {}
    Context(Buffer& buffer)
        : m_buffer(&buffer) {}

    Buffer& buffer() const
    {
        if (not has_buffer())
            throw runtime_error("no buffer in context");
        return *m_buffer;
    }
    bool has_buffer() const { return m_buffer; }

    Editor& editor() const
    {
        if (not has_editor())
            throw runtime_error("no editor in context");
        return *m_editor.get();
    }
    bool has_editor() const { return m_editor; }

    Window& window() const
    {
        if (not has_window())
            throw runtime_error("no window in context");
        return *dynamic_cast<Window*>(m_editor.get());
    }
    bool has_window() const { return m_editor and dynamic_cast<Window*>(m_editor.get()); }

    OptionManager& option_manager() const
    {
        if (has_window())
            return window().option_manager();
        if (has_buffer())
            return buffer().option_manager();
        return GlobalOptionManager::instance();
    }

    int numeric_param() const { return m_numeric_param; }
    void numeric_param(int param) { m_numeric_param = param; }

public:
    safe_ptr<Editor> m_editor;
    safe_ptr<Buffer> m_buffer;

    int m_numeric_param = 0;
};

}
#endif // context_hh_INCLUDED
<|endoftext|>


<commit_before>#ifndef STAN_MATH_PRIM_ARR_ERR_IS_ORDERED_HPP
#define STAN_MATH_PRIM_ARR_ERR_IS_ORDERED_HPP

#include <vector>
#include <string>

namespace stan {
namespace math {

/**
 * Return true if the vector is sorted into strictly
 * increasing order.s
 * @tparam T_y Type of scalar, requires class method .size()
 * @param y std::vector to test
 * @return true if vector is sorted in ascending order
 */
template <typename T_y>
inline bool is_ordered(const std::vector<T_y>& y) {
  for (size_t n = 1; n < y.size(); ++n) {
    if (!(y[n] > y[n - 1]))
      return false;
  }
  return true;
}

}  // namespace math
}  // namespace stan
#endif
<commit_msg>Update is_ordered.hpp<commit_after>#ifndef STAN_MATH_PRIM_ARR_ERR_IS_ORDERED_HPP
#define STAN_MATH_PRIM_ARR_ERR_IS_ORDERED_HPP

#include <vector>
#include <string>

namespace stan {
namespace math {

/**
 * Return true if the vector is sorted into strictly
 * increasing order.
 * @tparam T_y Type of scalar, requires class method .size()
 * @param y std::vector to test
 * @return true if vector is sorted in ascending order
 */
template <typename T_y>
inline bool is_ordered(const std::vector<T_y>& y) {
  for (size_t n = 1; n < y.size(); ++n) {
    if (!(y[n] > y[n - 1]))
      return false;
  }
  return true;
}

}  // namespace math
}  // namespace stan
#endif
<|endoftext|>


<commit_before>/**
 *  Extension.cpp
 *
 *  Starting point for the REACT-PHP-CPP extension. In this file all
 *  classes and methods that are defined by the extension are
 *  registered to PHP
 *
 *  @copyright 2014 Copernica BV
 */

/**
 *  Dependencies
 */
#include "loop.h"
#include "timeoutwatcher.h"
#include "intervalwatcher.h"
#include "readwatcher.h"
#include "writewatcher.h"
#include "synchronizewatcher.h"
#include "connection.h"
#include "statement.h"
#include "parameter.h"
#include "localparameter.h"
#include "result.h"

// Symbols are exported according to the "C" language
extern "C"
{
    // export the "get_module" function that will be called by the Zend engine
    PHPCPP_EXPORT void *get_module()
    {
        // create extension
        static Php::Extension extension("REACT-PHP-CPP","0.1");

        // create a namespace
        Php::Namespace async("Async");

        // the loop class
        Php::Class<ReactPhp::Loop> loop("Loop");
        loop.method("now", &ReactPhp::Loop::now);
        loop.method("run", &ReactPhp::Loop::run);
        loop.method("step", &ReactPhp::Loop::step);
        loop.method("stop", &ReactPhp::Loop::stop);
        loop.method("resume", &ReactPhp::Loop::resume);
        loop.method("suspend", &ReactPhp::Loop::suspend);
        loop.method("onTimeout", &ReactPhp::Loop::onTimeout);
        loop.method("onInterval", &ReactPhp::Loop::onInterval);
        loop.method("onReadable", &ReactPhp::Loop::onReadable);
        loop.method("onWritable", &ReactPhp::Loop::onWritable);
        loop.method("onSynchronize", &ReactPhp::Loop::onSynchronize);

        // the timer watcher class
        Php::Class<ReactPhp::TimeoutWatcher> timeoutWatcher("TimeoutWatcher");
        timeoutWatcher.method("__construct", &ReactPhp::TimeoutWatcher::__construct);
        timeoutWatcher.method("start", &ReactPhp::TimeoutWatcher::start);
        timeoutWatcher.method("cancel", &ReactPhp::TimeoutWatcher::cancel);
        timeoutWatcher.method("set", &ReactPhp::TimeoutWatcher::set);

	// the read watcher class
	Php::Class<ReactPhp::ReadWatcher> readWatcher("ReadWatcher");
	readWatcher.method("__construct", &ReactPhp::ReadWatcher::__construct);
	readWatcher.method("cancel", &ReactPhp::ReadWatcher::cancel);
	readWatcher.method("resume", &ReactPhp::ReadWatcher::resume);

	// the write watcher class
	Php::Class<ReactPhp::WriteWatcher> writeWatcher("WriteWatcher");
	writeWatcher.method("__construct", &ReactPhp::WriteWatcher::__construct);
	writeWatcher.method("cancel", &ReactPhp::WriteWatcher::cancel);
	writeWatcher.method("resume", &ReactPhp::WriteWatcher::resume);

	// the interval watcher class
	Php::Class<ReactPhp::IntervalWatcher> intervalWatcher("IntervalWatcher");
	intervalWatcher.method("__construct", &ReactPhp::IntervalWatcher::__construct);
	intervalWatcher.method("start", &ReactPhp::IntervalWatcher::start);
        intervalWatcher.method("cancel", &ReactPhp::IntervalWatcher::cancel);
        intervalWatcher.method("set", &ReactPhp::IntervalWatcher::set);

	// the synchronize watcher class
	Php::Class<ReactPhp::SynchronizeWatcher> synchronizeWatcher("SynchronizeWatcher");
	synchronizeWatcher.method("__construct", &ReactPhp::SynchronizeWatcher::__construct);
	synchronizeWatcher.method("synchronize", &ReactPhp::SynchronizeWatcher::synchronize);
	synchronizeWatcher.method("cancel", &ReactPhp::SynchronizeWatcher::cancel);

	// the connection class
	Php::Class<ReactPhp::Connection> connection("Connection");
	connection.method("__construct", &ReactPhp::Connection::__construct);
	connection.method("query", &ReactPhp::Connection::query);

	// the statement class
	Php::Class<ReactPhp::Statement> statement("Statement");
	statement.method("__construct", &ReactPhp::Statement::__construct);
	statement.method("execute", &ReactPhp::Statement::execute);
	statement.method("executeQuery", &ReactPhp::Statement::executeQuery);

	// the parameter class
	Php::Class<ReactPhp::Parameter> parameter("Parameter");
	parameter.method("__construct", &ReactPhp::Parameter::__construct);

	// the local parameter class
	Php::Class<ReactPhp::LocalParameter> localParameter("Parameter");
	localParameter.method("__construct", &ReactPhp::LocalParameter::__construct);

	// the result class
	Php::Class<ReactPhp::Result> result("Result");
	result.method("valid", &ReactPhp::Result::valid);
	result.method("size", &ReactPhp::Result::size);
	result.method("begin", &ReactPhp::Result::begin);
	result.method("end", &ReactPhp::Result::end);
	result.method("fetchRow", &ReactPhp::Result::fetchRow);

	// the result row class
	Php::Class<ReactPhp::ResultRow> resultRow("ResultRow");

	// the result field class
	Php::Class<ReactPhp::ResultField> resultField("ResultField");

        // add all classes to the namespace
        async.add(loop);
        async.add(timeoutWatcher);
        async.add(readWatcher);
        async.add(writeWatcher);
        async.add(intervalWatcher);
        async.add(synchronizeWatcher);
        async.add(connection);
        async.add(statement);
        async.add(parameter);
        async.add(result);
        async.add(localParameter);
        async.add(resultRow);
        async.add(resultField);

	// add the namespace to the extension
        extension.add(async);

        // return the extension module
        return extension.module();
    }
}
<commit_msg>Updated extension.cpp<commit_after>/**
 *	Extension.cpp
 *
 *	Starting point for the event loop extension. In this file all
 *	classes and methods that are defined by the extension are
 *	registered to PHP
 *
 * 	@copyright 2014 Copernica BV
 */

/**
 *  Dependencies
 */
#include "loop.h"
#include "timeoutwatcher.h"
#include "intervalwatcher.h"
#include "readwatcher.h"
#include "writewatcher.h"
#include "synchronizewatcher.h"
#include "signalwatcher.h"
#include "statuswatcher.h"
#include "resolver.h"
#include "connection.h"
#include "statement.h"
#include "parameter.h"
#include "localparameter.h"
#include "result.h"
#include "resolverresult.h"

// Symbols are exported according to the "C" language
extern "C"
{
    // export the "get_module" function that will be called by the Zend engine
    PHPCPP_EXPORT void *get_module()
    {
        // create extension
        static Php::Extension extension("REACT-PHP-CPP","0.1");

        // create a namespace
        Php::Namespace async("Async");

        // the loop class
        Php::Class<ReactPhp::Loop> loop("Loop");
        loop.method("now", &ReactPhp::Loop::now);
        loop.method("run", &ReactPhp::Loop::run);
        loop.method("step", &ReactPhp::Loop::step);
        loop.method("stop", &ReactPhp::Loop::stop);
        loop.method("resume", &ReactPhp::Loop::resume);
        loop.method("suspend", &ReactPhp::Loop::suspend);
        loop.method("onTimeout", &ReactPhp::Loop::onTimeout);
        loop.method("onInterval", &ReactPhp::Loop::onInterval);
        loop.method("onReadable", &ReactPhp::Loop::onReadable);
        loop.method("onWritable", &ReactPhp::Loop::onWritable);
        loop.method("onSynchronize", &ReactPhp::Loop::onSynchronize);
        loop.method("onSignal", &ReactPhp::Loop::onSignal);
        loop.method("onStatusChange", &ReactPhp::Loop::onStatusChange);

        // the timer watcher class
        Php::Class<ReactPhp::TimeoutWatcher> timeoutWatcher("TimeoutWatcher");
        timeoutWatcher.method("__construct", &ReactPhp::TimeoutWatcher::__construct);
        timeoutWatcher.method("start", &ReactPhp::TimeoutWatcher::start);
        timeoutWatcher.method("cancel", &ReactPhp::TimeoutWatcher::cancel);
        timeoutWatcher.method("set", &ReactPhp::TimeoutWatcher::set);

		// the read watcher class
		Php::Class<ReactPhp::ReadWatcher> readWatcher("ReadWatcher");
		readWatcher.method("__construct", &ReactPhp::ReadWatcher::__construct);
		readWatcher.method("cancel", &ReactPhp::ReadWatcher::cancel);
		readWatcher.method("resume", &ReactPhp::ReadWatcher::resume);

		// the write watcher class
		Php::Class<ReactPhp::WriteWatcher> writeWatcher("WriteWatcher");
		writeWatcher.method("__construct", &ReactPhp::WriteWatcher::__construct);
		writeWatcher.method("cancel", &ReactPhp::WriteWatcher::cancel);
		writeWatcher.method("resume", &ReactPhp::WriteWatcher::resume);

		// the interval watcher class
		Php::Class<ReactPhp::IntervalWatcher> intervalWatcher("IntervalWatcher");
		intervalWatcher.method("__construct", &ReactPhp::IntervalWatcher::__construct);
		intervalWatcher.method("start", &ReactPhp::IntervalWatcher::start);
        intervalWatcher.method("cancel", &ReactPhp::IntervalWatcher::cancel);
        intervalWatcher.method("set", &ReactPhp::IntervalWatcher::set);

		// the synchronize watcher class
		Php::Class<ReactPhp::SynchronizeWatcher> synchronizeWatcher("SynchronizeWatcher");
		synchronizeWatcher.method("__construct", &ReactPhp::SynchronizeWatcher::__construct);
		synchronizeWatcher.method("synchronize", &ReactPhp::SynchronizeWatcher::synchronize);
		synchronizeWatcher.method("cancel", &ReactPhp::SynchronizeWatcher::cancel);

		// the signal watcher class
		Php::Class<ReactPhp::SignalWatcher> signalWatcher("SignalWatcher");
        signalWatcher.method("__construct", &ReactPhp::SignalWatcher::__construct);
        signalWatcher.method("start", &ReactPhp::SignalWatcher::start);
        signalWatcher.method("cancel", &ReactPhp::SignalWatcher::cancel);

        // the staus watcher class
        Php::Class<ReactPhp::StatusWatcher> statusWatcher("StatusWatcher");
        statusWatcher.method("__construct", &ReactPhp::StatusWatcher::__construct);
        statusWatcher.method("start", &ReactPhp::StatusWatcher::start);
        statusWatcher.method("cancel", &ReactPhp::StatusWatcher::cancel);

        // the resolver class
        Php::Class<ReactPhp::Resolver> resolver("Resolver");
        resolver.method("__construct", &ReactPhp::Resolver::__construct);
        resolver.method("ip", &ReactPhp::Resolver::ip);
        resolver.method("mx", &ReactPhp::Resolver::mx);

		// the connection class
		Php::Class<ReactPhp::Connection> connection("Connection");
		connection.method("__construct", &ReactPhp::Connection::__construct);
		connection.method("query", &ReactPhp::Connection::query);

		// the statement class
		Php::Class<ReactPhp::Statement> statement("Statement");
		statement.method("__construct", &ReactPhp::Statement::__construct);
		statement.method("execute", &ReactPhp::Statement::execute);
		statement.method("executeQuery", &ReactPhp::Statement::executeQuery);

		// the parameter class
		Php::Class<ReactPhp::Parameter> parameter("Parameter");
		parameter.method("__construct", &ReactPhp::Parameter::__construct);

		// the local parameter class
		Php::Class<ReactPhp::LocalParameter> localParameter("Parameter");
		localParameter.method("__construct", &ReactPhp::LocalParameter::__construct);

		// the result class
		Php::Class<ReactPhp::Result> result("Result");
		result.method("valid", &ReactPhp::Result::valid);
		result.method("size", &ReactPhp::Result::size);
		result.method("begin", &ReactPhp::Result::begin);
		result.method("end", &ReactPhp::Result::end);
		result.method("fetchRow", &ReactPhp::Result::fetchRow);

		// the result row class
		Php::Class<ReactPhp::ResultRow> resultRow("ResultRow");

		// the result field class
		Php::Class<ReactPhp::ResultField> resultField("ResultField");

		// the resolver result class
		Php::Class<ReactPhp::ResolverResult> resolverResult("ResolverResult");

        // add all classes to the namespace
        async.add(loop);
        async.add(timeoutWatcher);
        async.add(readWatcher);
        async.add(writeWatcher);
        async.add(intervalWatcher);
        async.add(synchronizeWatcher);
        async.add(signalWatcher);
        async.add(statusWatcher);
        async.add(resolver);
        async.add(connection);
        async.add(statement);
        async.add(parameter);
        async.add(result);
        async.add(localParameter);
        async.add(resultRow);
        async.add(resultField);
        async.add(resolverResult);

		// add the namespace to the extension
        extension.add(async);

        // return the extension module
        return extension.module();
    }
}

<|endoftext|>


<commit_before>#include "device.h"

#ifndef QT_NO_DBUS
#include "systemhelperdbus.h"
#endif

Device::Device(const QString &p, DeviceType t, const QString &l, const QString &u, QObject *parent) :
    QObject(parent)
  , m_path(p)
  , m_type(t)
  , m_label(l)
  , m_uuid(u)
{
#ifndef QT_NO_DBUS
    m_helper = qobject_cast<SystemHelperDBus*>(parent);
#endif
    emit changed();
}

void Device::mount()
{
    qDebug() << "Device::mount()";
#ifndef QT_NO_DBUS
    m_helper->mount(m_path);
#endif
}

void Device::unmount()
{
#ifndef QT_NO_DBUS
    m_helper->unmount(m_path);
#endif
}

void Device::eject()
{
#ifndef QT_NO_DBUS
    m_helper->eject(m_path);
#endif
}
<commit_msg>remove debug message<commit_after>#include "device.h"

#ifndef QT_NO_DBUS
#include "systemhelperdbus.h"
#endif

Device::Device(const QString &p, DeviceType t, const QString &l, const QString &u, QObject *parent) :
    QObject(parent)
  , m_path(p)
  , m_type(t)
  , m_label(l)
  , m_uuid(u)
{
#ifndef QT_NO_DBUS
    m_helper = qobject_cast<SystemHelperDBus*>(parent);
#endif
    emit changed();
}

void Device::mount()
{
#ifndef QT_NO_DBUS
    m_helper->mount(m_path);
#endif
}

void Device::unmount()
{
#ifndef QT_NO_DBUS
    m_helper->unmount(m_path);
#endif
}

void Device::eject()
{
#ifndef QT_NO_DBUS
    m_helper->eject(m_path);
#endif
}
<|endoftext|>


<commit_before>#include "device.h"
#include "sysex/commands.h"
#include "sysex/deviceinfo.h"
#include "sysex/getcommands.h"
#include "sysex/infos.h"
#include "sysex/midi.h"

#include <array>
#include <cstring>
#include <iostream>
#include <sstream>
#include <unistd.h>

Device::Device(int inPortNumber, int outPortNumber, long serialNumber,
               int productId) {
  this->inPortNumber = inPortNumber;
  this->outPortNumber = outPortNumber;
  this->serialNumber = new MIDISysexValue(serialNumber, 5);
  this->productId = new MIDISysexValue(productId, 2);
  setupMidi();
}

#ifdef __MIO_SIMULATE__

Device::Device(int inPortNumber, int outPortNumber, long serialNumber,
               int productId, std::string modelName, std::string deviceName) {
  this->inPortNumber = inPortNumber;
  this->outPortNumber = outPortNumber;
  this->serialNumber = new MIDISysexValue(serialNumber, 5);
  this->productId = new MIDISysexValue(productId, 2);
  this->modelName = modelName;
  this->deviceName = deviceName;
  this->deviceIsSimulated = true;
}

Commands *Device::simulateCommands() {
  BYTE_VECTOR *message = new BYTE_VECTOR({0xF0});
  message->insert(message->end(), getFullHeader()->begin(),
                  getFullHeader()->end());
  message->push_back(0x00);
  message->push_back(0x01);
  message->push_back(0x00);
  message->push_back(SysExMessage::RET_COMMAND_LIST);
  message->push_back(0x00);
  message->push_back(0x06);
  message->insert(message->end(), {0x05, 0x07, 0x08, 0x09, 0x0b, 0x0c});
  commands = new Commands(SysExMessage::RET_COMMAND_LIST, message, this);
  commands->parseAnswerData();
  return commands;
}

#endif //__MIO_SIMULATE__

Device::~Device() {
  if (midiin) {
    if (midiin->isPortOpen())
      midiin->closePort();
    delete midiin;
  }
  if (midiout) {
    if (midiout->isPortOpen())
      midiout->closePort();
    delete midiout;
  }
}

BYTE_VECTOR *Device::getManufacturerHeader() {
  if (Device::manufacturerHeader == 0) {
    manufacturerHeader = new BYTE_VECTOR();
    manufacturerHeader->push_back(MANUFACTURER_SYSEX_ID[0]);
    manufacturerHeader->push_back(MANUFACTURER_SYSEX_ID[1]);
    manufacturerHeader->push_back(MANUFACTURER_SYSEX_ID[2]);
  }
  return manufacturerHeader;
}

BYTE_VECTOR *Device::getDeviceHeader() {
  if (deviceHeader == 0) {
    deviceHeader = new BYTE_VECTOR();
    deviceHeader->reserve(productId->getByteValue()->size() +
                          serialNumber->getByteValue()->size());
    deviceHeader->insert(deviceHeader->end(),
                         productId->getByteValue()->begin(),
                         productId->getByteValue()->end());
    deviceHeader->insert(deviceHeader->end(),
                         serialNumber->getByteValue()->begin(),
                         serialNumber->getByteValue()->end());
  }
  return deviceHeader;
}

BYTE_VECTOR *Device::getFullHeader() {
  if (fullHeader == 0) {
    fullHeader = new BYTE_VECTOR();
    fullHeader->reserve(Device::getManufacturerHeader()->size() +
                        getDeviceHeader()->size() + 1);
    fullHeader->insert(fullHeader->end(),
                       Device::getManufacturerHeader()->begin(),
                       Device::getManufacturerHeader()->end());
    fullHeader->push_back(Device::MESSAGE_CLASS);
    fullHeader->insert(fullHeader->end(), getDeviceHeader()->begin(),
                       getDeviceHeader()->end());
  }
  return fullHeader;
}

void Device::setupMidi() {
  std::stringstream name;
  name << "MioConfig In " << serialNumber->getLongValue();
  midiin = MIDI::createMidiIn(name.str());
  midiin->openPort(inPortNumber);
  name << "MioConfig Out " << serialNumber->getLongValue();
  midiout = MIDI::createMidiOut(name.str());
  midiout->openPort(outPortNumber);
}

void Device::sentSysex(BYTE_VECTOR *data) {
  usleep(sysexWaitTime);
  midiout->sendMessage(data);
}

BYTE_VECTOR *Device::retrieveSysex() {
  usleep(sysexWaitTime);
  BYTE_VECTOR *data = new BYTE_VECTOR();
  midiin->getMessage(data);
  if (checkSysex(data))
    return data;
  return 0;
}

bool Device::checkSysex(BYTE_VECTOR *data) {
  BYTE_VECTOR *dataHeader =
      new BYTE_VECTOR(data->begin() + 1, data->begin() + 12);
  BYTE_VECTOR *localHeader = getFullHeader();
  return MIDI::compareByteVector(dataHeader, localHeader);
}

void Device::queryDeviceInfo() {
  GetCommands *c = new GetCommands(this);
  c->setDebug(true);
#ifdef __MIO_SIMULATE__
  commands = simulateCommands();
#else
  commands = (Commands *)c->query();
#endif
  if (commands == 0) {
    std::cerr << "can not query supported commands";
    return;
  }

#if __MIO_SIMULATE__
  if (!deviceIsSimulated) {
#endif //__MIO_SIMULATE
    if (commands->isCommandSupported(SysExMessage::GET_INFO_LIST)) {
      Infos *i = new Infos(this);
      i->execute();
      Infos *ia = (Infos *)i->getAnswer();
    }

    DeviceInfo *di = new DeviceInfo(this);
    di->execute();
    DeviceInfo *dia = (DeviceInfo *)di->getAnswer();
    deviceName = dia->getDataAsString();

    di->setInfoItem(DeviceInfo::ACESSORY_NAME);
    di->execute();
    dia = (DeviceInfo *)di->getAnswer();
    modelName = dia->getDataAsString();

    di->setInfoItem(DeviceInfo::SERIAL_NUMBER);
    di->execute();
    dia = (DeviceInfo *)di->getAnswer();
    serialNumberString = dia->getDataAsString();
#ifdef __MIO_SIMULATE__
  }
#endif //__MIO_SIMULATE__
}

BYTE_VECTOR *Device::nextTransactionId() {
  if (transactionId > 16000)
    transactionId = 0;
  BYTE_VECTOR *v = MIDI::byteSplit(++transactionId, 2);
  return v;
}

BYTE_VECTOR *Device::manufacturerHeader = 0;
<commit_msg>added more commands to simulated "Commands" class<commit_after>#include "device.h"
#include "sysex/commands.h"
#include "sysex/deviceinfo.h"
#include "sysex/getcommands.h"
#include "sysex/infos.h"
#include "sysex/midi.h"

#include <array>
#include <cstring>
#include <iostream>
#include <sstream>
#include <unistd.h>

Device::Device(int inPortNumber, int outPortNumber, long serialNumber,
               int productId) {
  this->inPortNumber = inPortNumber;
  this->outPortNumber = outPortNumber;
  this->serialNumber = new MIDISysexValue(serialNumber, 5);
  this->productId = new MIDISysexValue(productId, 2);
  setupMidi();
}

#ifdef __MIO_SIMULATE__

Device::Device(int inPortNumber, int outPortNumber, long serialNumber,
               int productId, std::string modelName, std::string deviceName) {
  this->inPortNumber = inPortNumber;
  this->outPortNumber = outPortNumber;
  this->serialNumber = new MIDISysexValue(serialNumber, 5);
  this->productId = new MIDISysexValue(productId, 2);
  this->modelName = modelName;
  this->deviceName = deviceName;
  this->deviceIsSimulated = true;
}

Commands *Device::simulateCommands() {
  BYTE_VECTOR *message = new BYTE_VECTOR({0xF0});
  message->insert(message->end(), getFullHeader()->begin(),
                  getFullHeader()->end());
  message->push_back(0x00);
  message->push_back(0x01);
  message->push_back(0x00);
  message->push_back(SysExMessage::RET_COMMAND_LIST);
  message->push_back(0x00);
	BYTE_VECTOR *allowedCommands = new BYTE_VECTOR();
	allowedCommands->insert(
			allowedCommands->end(),
			{SysExMessage::GET_INFO_LIST, SysExMessage::GET_DEVICE_INFO,
			 SysExMessage::RET_SET_DEVICE_INFO, SysExMessage::GET_RESET_LIST,
			 SysExMessage::GET_SAVE_RESTORE_LIST,
			 SysExMessage::GET_ETHERNET_PORT_INFO});
	message->push_back(allowedCommands->size());
	message->insert(message->end(), allowedCommands->begin(),
									allowedCommands->end());
	Commands *commands =
			new Commands(SysExMessage::RET_COMMAND_LIST, message, this);
  commands->parseAnswerData();
  return commands;
}

#endif //__MIO_SIMULATE__

Device::~Device() {
  if (midiin) {
    if (midiin->isPortOpen())
      midiin->closePort();
    delete midiin;
  }
  if (midiout) {
    if (midiout->isPortOpen())
      midiout->closePort();
    delete midiout;
  }
}

BYTE_VECTOR *Device::getManufacturerHeader() {
  if (Device::manufacturerHeader == 0) {
    manufacturerHeader = new BYTE_VECTOR();
    manufacturerHeader->push_back(MANUFACTURER_SYSEX_ID[0]);
    manufacturerHeader->push_back(MANUFACTURER_SYSEX_ID[1]);
    manufacturerHeader->push_back(MANUFACTURER_SYSEX_ID[2]);
  }
  return manufacturerHeader;
}

BYTE_VECTOR *Device::getDeviceHeader() {
  if (deviceHeader == 0) {
    deviceHeader = new BYTE_VECTOR();
    deviceHeader->reserve(productId->getByteValue()->size() +
                          serialNumber->getByteValue()->size());
    deviceHeader->insert(deviceHeader->end(),
                         productId->getByteValue()->begin(),
                         productId->getByteValue()->end());
    deviceHeader->insert(deviceHeader->end(),
                         serialNumber->getByteValue()->begin(),
                         serialNumber->getByteValue()->end());
  }
  return deviceHeader;
}

BYTE_VECTOR *Device::getFullHeader() {
  if (fullHeader == 0) {
    fullHeader = new BYTE_VECTOR();
    fullHeader->reserve(Device::getManufacturerHeader()->size() +
                        getDeviceHeader()->size() + 1);
    fullHeader->insert(fullHeader->end(),
                       Device::getManufacturerHeader()->begin(),
                       Device::getManufacturerHeader()->end());
    fullHeader->push_back(Device::MESSAGE_CLASS);
    fullHeader->insert(fullHeader->end(), getDeviceHeader()->begin(),
                       getDeviceHeader()->end());
  }
  return fullHeader;
}

void Device::setupMidi() {
  std::stringstream name;
  name << "MioConfig In " << serialNumber->getLongValue();
  midiin = MIDI::createMidiIn(name.str());
  midiin->openPort(inPortNumber);
  name << "MioConfig Out " << serialNumber->getLongValue();
  midiout = MIDI::createMidiOut(name.str());
  midiout->openPort(outPortNumber);
}

void Device::sentSysex(BYTE_VECTOR *data) {
  usleep(sysexWaitTime);
  midiout->sendMessage(data);
}

BYTE_VECTOR *Device::retrieveSysex() {
  usleep(sysexWaitTime);
  BYTE_VECTOR *data = new BYTE_VECTOR();
  midiin->getMessage(data);
  if (checkSysex(data))
    return data;
  return 0;
}

bool Device::checkSysex(BYTE_VECTOR *data) {
  BYTE_VECTOR *dataHeader =
      new BYTE_VECTOR(data->begin() + 1, data->begin() + 12);
  BYTE_VECTOR *localHeader = getFullHeader();
  return MIDI::compareByteVector(dataHeader, localHeader);
}

void Device::queryDeviceInfo() {
  GetCommands *c = new GetCommands(this);
  c->setDebug(true);
#ifdef __MIO_SIMULATE__
  commands = simulateCommands();
#else
  commands = (Commands *)c->query();
#endif
  if (commands == 0) {
    std::cerr << "can not query supported commands";
    return;
  }

#if __MIO_SIMULATE__
  if (!deviceIsSimulated) {
#endif //__MIO_SIMULATE
    if (commands->isCommandSupported(SysExMessage::GET_INFO_LIST)) {
      Infos *i = new Infos(this);
      i->execute();
      Infos *ia = (Infos *)i->getAnswer();
    }

    DeviceInfo *di = new DeviceInfo(this);
    di->execute();
    DeviceInfo *dia = (DeviceInfo *)di->getAnswer();
    deviceName = dia->getDataAsString();

    di->setInfoItem(DeviceInfo::ACESSORY_NAME);
    di->execute();
    dia = (DeviceInfo *)di->getAnswer();
    modelName = dia->getDataAsString();

    di->setInfoItem(DeviceInfo::SERIAL_NUMBER);
    di->execute();
    dia = (DeviceInfo *)di->getAnswer();
    serialNumberString = dia->getDataAsString();
#ifdef __MIO_SIMULATE__
  }
#endif //__MIO_SIMULATE__
}

BYTE_VECTOR *Device::nextTransactionId() {
  if (transactionId > 16000)
    transactionId = 0;
  BYTE_VECTOR *v = MIDI::byteSplit(++transactionId, 2);
  return v;
}

BYTE_VECTOR *Device::manufacturerHeader = 0;
<|endoftext|>


<commit_before>#include "cylvionpp/field.h"

#include <algorithm>
#include <array>

#include "cylvionpp/card.h"
#include "cylvionpp/stack.h"

namespace cylvionpp {
namespace core {

namespace {

class FieldImpl: public Field {
public:
    bool Empty() const override;

    const std::unique_ptr<Card> & Peek(size_t row, size_t col) const override;
    bool Put(size_t row, size_t col, std::unique_ptr<Card> &&) override;
    bool Move(size_t row, size_t col, size_t to_row, size_t toCol) override;
    std::unique_ptr<Card> Remove(size_t row, size_t col) override;

    const Stack & GetRavageStack(size_t row) const override;
    Stack & GetRavageStack(size_t row) override;

private:
    using Row = std::array<std::unique_ptr<Card>, 5>;
    static bool RowEmpty(const Row &);

    std::array<Row, 4> c;
};

bool
FieldImpl::RowEmpty(const FieldImpl::Row & row)
{
    return std::none_of(row.begin(), row.end(), [](const std::unique_ptr<Card> & card){ return card.get(); });
}

bool
FieldImpl::Empty() const
{
    return std::all_of(c.begin(), c.end(), FieldImpl::RowEmpty);
}

const std::unique_ptr<Card> &
FieldImpl::Peek(size_t row, size_t col) const
{
    return c[row][col];
}

bool
FieldImpl::Put(size_t row, size_t col, std::unique_ptr<Card> && card)
{
    if (c[row][col].get()) {
        return false;
    }
    c[row][col] = std::move(card);
    return true;
}

bool
FieldImpl::Move(size_t row, size_t col, size_t toRow, size_t toCol)
{
    if (!c[row][col].get() || c[toRow][toCol].get()) {
        return false;
    }
    c[toRow][toCol] = std::move(c[row][col]);
    return true;
}

std::unique_ptr<Card>
FieldImpl::Remove(size_t row, size_t col)
{
    if (!c[row][col]) {
        throw std::logic_error("Remove null card.");
    }
    return std::move(c[row][col]);
}

} // namespace

Field::~Field()
{/* Empty. */}

std::unique_ptr<Field>
Field::New()
{
    return std::make_unique<FieldImpl>();
}

} // namespace core
} // namespace cylvionpp
<commit_msg>Full impl of Stack<commit_after>#include "cylvionpp/field.h"

#include <algorithm>
#include <array>

#include "cylvionpp/card.h"
#include "cylvionpp/stack.h"

namespace cylvionpp {
namespace core {

namespace {

class FieldImpl: public Field {
public:
    FieldImpl();

    bool Empty() const override;

    const std::unique_ptr<Card> & Peek(size_t row, size_t col) const override;
    bool Put(size_t row, size_t col, std::unique_ptr<Card> &&) override;
    bool Move(size_t row, size_t col, size_t to_row, size_t toCol) override;
    std::unique_ptr<Card> Remove(size_t row, size_t col) override;

    const Stack & GetRavageStack(size_t row) const override;
    Stack & GetRavageStack(size_t row) override;

private:
    using Row = std::array<std::unique_ptr<Card>, 5>;
    static bool RowEmpty(const Row &);

    std::array<Row, 4> c;
    std::array<std::unique_ptr<Stack>, 4> s;
};

FieldImpl::FieldImpl():
    c(),
    s()
{
    for (auto && stack: s) {
        stack = Stack::New();
    }
}

bool
FieldImpl::RowEmpty(const FieldImpl::Row & row)
{
    return std::none_of(row.begin(), row.end(), [](const std::unique_ptr<Card> & card){ return card.get(); });
}

bool
FieldImpl::Empty() const
{
    return std::all_of(c.begin(), c.end(), FieldImpl::RowEmpty);
}

const std::unique_ptr<Card> &
FieldImpl::Peek(size_t row, size_t col) const
{
    return c[row][col];
}

bool
FieldImpl::Put(size_t row, size_t col, std::unique_ptr<Card> && card)
{
    if (c[row][col].get()) {
        return false;
    }
    c[row][col] = std::move(card);
    return true;
}

bool
FieldImpl::Move(size_t row, size_t col, size_t toRow, size_t toCol)
{
    if (!c[row][col].get() || c[toRow][toCol].get()) {
        return false;
    }
    c[toRow][toCol] = std::move(c[row][col]);
    return true;
}

std::unique_ptr<Card>
FieldImpl::Remove(size_t row, size_t col)
{
    if (!c[row][col]) {
        throw std::logic_error("Remove null card.");
    }
    return std::move(c[row][col]);
}

const Stack &
FieldImpl::GetRavageStack(size_t row) const
{
    return *s[row];
}

Stack &
FieldImpl::GetRavageStack(size_t row)
{
    return const_cast<Stack &>(static_cast<const FieldImpl *>(this)->GetRavageStack(row));
}

} // namespace

Field::~Field()
{/* Empty. */}

std::unique_ptr<Field>
Field::New()
{
    return std::make_unique<FieldImpl>();
}

} // namespace core
} // namespace cylvionpp
<|endoftext|>


<commit_before>/*
 * Copyright 2013 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "folly/FileUtil.h"

#include <cerrno>
#ifdef __APPLE__
#include <fcntl.h>
#endif

#include "folly/detail/FileUtilDetail.h"

namespace folly {

using namespace fileutil_detail;

int openNoInt(const char* name, int flags, mode_t mode) {
  return wrapNoInt(open, name, flags, mode);
}

int closeNoInt(int fd) {
  int r = close(fd);
  // Ignore EINTR.  On Linux, close() may only return EINTR after the file
  // descriptor has been closed, so you must not retry close() on EINTR --
  // in the best case, you'll get EBADF, and in the worst case, you'll end up
  // closing a different file (one opened from another thread).
  //
  // Interestingly enough, the Single Unix Specification says that the state
  // of the file descriptor is unspecified if close returns EINTR.  In that
  // case, the safe thing to do is also not to retry close() -- leaking a file
  // descriptor is probably better than closing the wrong file.
  if (r == -1 && errno == EINTR) {
    r = 0;
  }
  return r;
}

int fsyncNoInt(int fd) {
  return wrapNoInt(fsync, fd);
}

int fdatasyncNoInt(int fd) {
#ifndef __APPLE__
  return wrapNoInt(fdatasync, fd);
#else
  return wrapNoInt(fcntl, fd, F_FULLFSYNC);
#endif
}

int ftruncateNoInt(int fd, off_t len) {
  return wrapNoInt(ftruncate, fd, len);
}

int truncateNoInt(const char* path, off_t len) {
  return wrapNoInt(truncate, path, len);
}

ssize_t readNoInt(int fd, void* buf, size_t count) {
  return wrapNoInt(read, fd, buf, count);
}

ssize_t preadNoInt(int fd, void* buf, size_t count, off_t offset) {
  return wrapNoInt(pread, fd, buf, count, offset);
}

ssize_t readvNoInt(int fd, const iovec* iov, int count) {
  return wrapNoInt(writev, fd, iov, count);
}

ssize_t writeNoInt(int fd, const void* buf, size_t count) {
  return wrapNoInt(write, fd, buf, count);
}

ssize_t pwriteNoInt(int fd, const void* buf, size_t count, off_t offset) {
  return wrapNoInt(pwrite, fd, buf, count, offset);
}

ssize_t writevNoInt(int fd, const iovec* iov, int count) {
  return wrapNoInt(writev, fd, iov, count);
}

ssize_t readFull(int fd, void* buf, size_t count) {
  return wrapFull(read, fd, buf, count);
}

ssize_t preadFull(int fd, void* buf, size_t count, off_t offset) {
  return wrapFull(pread, fd, buf, count, offset);
}

ssize_t writeFull(int fd, const void* buf, size_t count) {
  return wrapFull(write, fd, const_cast<void*>(buf), count);
}

ssize_t pwriteFull(int fd, const void* buf, size_t count, off_t offset) {
  return wrapFull(pwrite, fd, const_cast<void*>(buf), count, offset);
}

ssize_t readvFull(int fd, iovec* iov, int count) {
  return wrapvFull(readv, fd, iov, count);
}

#ifdef FOLLY_HAVE_PREADV
ssize_t preadvFull(int fd, iovec* iov, int count, off_t offset) {
  return wrapvFull(preadv, fd, iov, count, offset);
}
#endif

ssize_t writevFull(int fd, iovec* iov, int count) {
  return wrapvFull(writev, fd, iov, count);
}

#ifdef FOLLY_HAVE_PWRITEV
ssize_t pwritevFull(int fd, iovec* iov, int count, off_t offset) {
  return wrapvFull(pwritev, fd, iov, count, offset);
}
#endif

}  // namespaces

<commit_msg>fix folly compilation on FreeBSD<commit_after>/*
 * Copyright 2013 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "folly/FileUtil.h"

#include <cerrno>
#ifdef __APPLE__
#include <fcntl.h>
#endif

#include "folly/detail/FileUtilDetail.h"

namespace folly {

using namespace fileutil_detail;

int openNoInt(const char* name, int flags, mode_t mode) {
  return wrapNoInt(open, name, flags, mode);
}

int closeNoInt(int fd) {
  int r = close(fd);
  // Ignore EINTR.  On Linux, close() may only return EINTR after the file
  // descriptor has been closed, so you must not retry close() on EINTR --
  // in the best case, you'll get EBADF, and in the worst case, you'll end up
  // closing a different file (one opened from another thread).
  //
  // Interestingly enough, the Single Unix Specification says that the state
  // of the file descriptor is unspecified if close returns EINTR.  In that
  // case, the safe thing to do is also not to retry close() -- leaking a file
  // descriptor is probably better than closing the wrong file.
  if (r == -1 && errno == EINTR) {
    r = 0;
  }
  return r;
}

int fsyncNoInt(int fd) {
  return wrapNoInt(fsync, fd);
}

int fdatasyncNoInt(int fd) {
#if defined(__APPLE__)
  return wrapNoInt(fcntl, fd, F_FULLFSYNC);
#elif defined(__FreeBSD__)
  return wrapNoInt(fsync, fd);
#else
  return wrapNoInt(fdatasync, fd);
#endif
}

int ftruncateNoInt(int fd, off_t len) {
  return wrapNoInt(ftruncate, fd, len);
}

int truncateNoInt(const char* path, off_t len) {
  return wrapNoInt(truncate, path, len);
}

ssize_t readNoInt(int fd, void* buf, size_t count) {
  return wrapNoInt(read, fd, buf, count);
}

ssize_t preadNoInt(int fd, void* buf, size_t count, off_t offset) {
  return wrapNoInt(pread, fd, buf, count, offset);
}

ssize_t readvNoInt(int fd, const iovec* iov, int count) {
  return wrapNoInt(writev, fd, iov, count);
}

ssize_t writeNoInt(int fd, const void* buf, size_t count) {
  return wrapNoInt(write, fd, buf, count);
}

ssize_t pwriteNoInt(int fd, const void* buf, size_t count, off_t offset) {
  return wrapNoInt(pwrite, fd, buf, count, offset);
}

ssize_t writevNoInt(int fd, const iovec* iov, int count) {
  return wrapNoInt(writev, fd, iov, count);
}

ssize_t readFull(int fd, void* buf, size_t count) {
  return wrapFull(read, fd, buf, count);
}

ssize_t preadFull(int fd, void* buf, size_t count, off_t offset) {
  return wrapFull(pread, fd, buf, count, offset);
}

ssize_t writeFull(int fd, const void* buf, size_t count) {
  return wrapFull(write, fd, const_cast<void*>(buf), count);
}

ssize_t pwriteFull(int fd, const void* buf, size_t count, off_t offset) {
  return wrapFull(pwrite, fd, const_cast<void*>(buf), count, offset);
}

ssize_t readvFull(int fd, iovec* iov, int count) {
  return wrapvFull(readv, fd, iov, count);
}

#ifdef FOLLY_HAVE_PREADV
ssize_t preadvFull(int fd, iovec* iov, int count, off_t offset) {
  return wrapvFull(preadv, fd, iov, count, offset);
}
#endif

ssize_t writevFull(int fd, iovec* iov, int count) {
  return wrapvFull(writev, fd, iov, count);
}

#ifdef FOLLY_HAVE_PWRITEV
ssize_t pwritevFull(int fd, iovec* iov, int count, off_t offset) {
  return wrapvFull(pwritev, fd, iov, count, offset);
}
#endif

}  // namespaces

<|endoftext|>


<commit_before>#include "stdafx.h"
#include "Storage.h"

Storage::Storage()
{
}

FoneOSString Storage::GetBasePath()
{
    char * prefPath;
#ifdef SIMULATOR_BUILD
    prefPath = SDL_GetPrefPath("Flippers", "foneOS");
#else
    prefPath = "/fone/";
#endif
	FoneOSString prefPathStr;

	prefPathStr = Utils::CharArrayToFoneOSString(prefPath);

	return prefPathStr;
}

FoneOSString Storage::GetFullPath(FoneOSString baseStr)
{
	return Storage::GetBasePath() + baseStr;
}

bool Storage::FileExists(FoneOSString fileName)
{
	std::ifstream test(Storage::GetFullPath(fileName));
	bool resp = test.good();
	test.close();
	return resp;
}

bool Storage::RemoveFile(FoneOSString fileName)
{
	// "Why isn't this called DeleteFile?"
	// "Because then Windows' macros would change it to DeleteFileW."
	if (!Storage::FileExists(fileName))
	{
		return false;
	}
	return remove(Utils::FoneOSStringToCharArray(Storage::GetFullPath(fileName))) == 0;
}

FoneOSString Storage::ReadAllText(FoneOSString fileName)
{
	FoneOSIFileStream file;
	file.open(Storage::GetFullPath(fileName));
	if (file.good())
	{
		FoneOSString retVal;
		FoneOSString chunk;
		bool firstTime = true;
		while (!file.eof())
		{
			if (firstTime)
			{
				firstTime = false;
			}
			else
			{
				retVal += STR(" ");
			}
			file >> chunk;
			retVal += chunk;
		}

		file.close();

		return retVal;
	}
	else
	{
		return STR("");
	}
}
<commit_msg>Change pref path organization name<commit_after>#include "stdafx.h"
#include "Storage.h"

Storage::Storage()
{
}

FoneOSString Storage::GetBasePath()
{
    char * prefPath;
#ifdef SIMULATOR_BUILD
    prefPath = SDL_GetPrefPath("foneOS", "foneOS");
#else
    prefPath = "/fone/";
#endif
	FoneOSString prefPathStr;

	prefPathStr = Utils::CharArrayToFoneOSString(prefPath);

	return prefPathStr;
}

FoneOSString Storage::GetFullPath(FoneOSString baseStr)
{
	return Storage::GetBasePath() + baseStr;
}

bool Storage::FileExists(FoneOSString fileName)
{
	std::ifstream test(Storage::GetFullPath(fileName));
	bool resp = test.good();
	test.close();
	return resp;
}

bool Storage::RemoveFile(FoneOSString fileName)
{
	// "Why isn't this called DeleteFile?"
	// "Because then Windows' macros would change it to DeleteFileW."
	if (!Storage::FileExists(fileName))
	{
		return false;
	}
	return remove(Utils::FoneOSStringToCharArray(Storage::GetFullPath(fileName))) == 0;
}

FoneOSString Storage::ReadAllText(FoneOSString fileName)
{
	FoneOSIFileStream file;
	file.open(Storage::GetFullPath(fileName));
	if (file.good())
	{
		FoneOSString retVal;
		FoneOSString chunk;
		bool firstTime = true;
		while (!file.eof())
		{
			if (firstTime)
			{
				firstTime = false;
			}
			else
			{
				retVal += STR(" ");
			}
			file >> chunk;
			retVal += chunk;
		}

		file.close();

		return retVal;
	}
	else
	{
		return STR("");
	}
}
<|endoftext|>


<commit_before>#include "football_field.h"
#include <QDebug>

#define keycontrast(KEY) (10 - (KEY))
#define red_win(X, Y) ((Y) == -26 && (X) <= 2 && (X) >= -2)
#define blue_win(X, Y) ((Y) == 26 && (X) <= 2 && (X) >= -2)

// Конструктор
FootballField::FootballField()
{
    // Зануляем массив.
    for(int i = 0; i < FIELD_WIDTH / PX_SCALE + 1; i++){
        for(int j = 0; j < FIELD_HEIGHT / PX_SCALE + 1; j++){
            points[i][j] = NULL;
        }
    }

    // Стартовая точка.
    FLD_POINT(0, 0) = new FPoint(0, 0);

    // Создаём ворота.
    FLD_POINT(-3, -25) = new FPoint(-3, -25, true);
    FLD_POINT( 3, -25) = new FPoint( 3, -25, true);
    FLD_POINT(-3,  25) = new FPoint(-3,  25, true);
    FLD_POINT( 3,  25) = new FPoint( 3,  25, true);

    // Создаём коробку (окружающие поле стены).
    for(int y = -26; y <= 26; y++){
        FLD_POINT(-20, y) = new FPoint(-20, y, true);
        FLD_POINT( 20, y) = new FPoint(20, y, true);
        if((y > -20 && y < -2) || (y > 2 && y < 20)){
            FLD_POINT(y,  26) = new FPoint(y, 26, true);
            FLD_POINT(y, -26) = new FPoint(y, -26, true);
        }
    }

    // Мячик изначально в позиции 0:0
    current_player = 1; // 1 (blue) -1 (red)
}

// Деструктор
FootballField::~FootballField(){
    //
    for(int i = 0; i < FIELD_WIDTH / PX_SCALE + 1; i++){
        for(int j = 0; j < FIELD_HEIGHT / PX_SCALE + 1; j++){
            delete points[i][j];
        }
    }
}

bool FootballField::try_step(int key){
    if (gameover)
        return false;

    if (penalty_mode){
        return try_penalty(key);
    }

    if (can_step(KEYS[key][0], KEYS[key][1])){
        signed char x = ball.x + KEYS[key][0],
                    y = ball.y + KEYS[key][1];
        if(red_win(x, y)){
            winner = -1;
            qDebug() << "red player winner!\n";
            gameover = true;
            show_ball = false;
        }
        if(blue_win(x, y)){
            winner = 1;
            qDebug() << "blue player winner!\n";
            gameover = true;
            show_ball = false;
        }
        if(gameover){
            steps.push_back(key * current_player);
            return true;
        }
        steps.push_back(key * current_player);
        FLD_POINT(x, y) = new FPoint(x, y);
        FLD_POINT(x, y)->push(FLD_POINT(ball.x, ball.y));
        FLD_POINT(ball.x, ball.y)->push(FLD_POINT(x, y));
        ball.step(KEYS[key][0], KEYS[key][1]);
        if(penalty_kick()){
            qDebug() << "PENALTY";
        }
        else if(current_step == 3){
            current_player *= -1;
            current_step = 1;
        }
        else
            ++current_step;

        return true;
    }
    return false;
}

bool FootballField::try_penalty(int key){
    signed char x = ball.x + KEYS[key][0],
                y = ball.y + KEYS[key][1];
    // Validates
    for(int i = 0; i < 6; i++){
        if (FLD_POINT(x, y) != NULL && FLD_POINT(x, y)->is_wall)
            return false;
        if(red_win(x, y)){
            winner = -1;
            qDebug() << "red player winner!\n";
            gameover = true;
            show_ball = false;
        }
        if(blue_win(x, y)){
            winner = 1;
            qDebug() << "blue player winner!\n";
            gameover = true;
            show_ball = false;
        }
        if(gameover){
            for(; i >= 0; i--)
                steps.push_back(key * current_player);
            return true;
        }
        x += KEYS[key][0];
        y += KEYS[key][1];
    }

    // return to first point
    x = ball.x + KEYS[key][0];
    y = ball.y + KEYS[key][1];
    // Real ball moves
    for(int i = 0; i < 6; i++){
        steps.push_back(key * current_player);
        if(FLD_POINT(x, y) == NULL)
            FLD_POINT(x, y) = new FPoint(x, y);
        FLD_POINT(x, y)->push(FLD_POINT(ball.x, ball.y));
        FLD_POINT(ball.x, ball.y)->push(FLD_POINT(x, y));
        ball.step(KEYS[key][0], KEYS[key][1]);
        x += KEYS[key][0];
        y += KEYS[key][1];
    }

    if(penalty_kick()){
        qDebug() << "one more PENALTY";
    }
    else if (current_step == 3) {
        current_player *= -1;
        current_step = 1;
    }
    else
        ++current_step;
    return true;
}

bool FootballField::can_step_from(signed char x, signed char y, int bx, int by){
    const int old_x = ball.x,
              old_y = ball.y;
    ball.x = bx;
    ball.y = by;
    bool result = can_step(x, y);
    ball.x = old_x;
    ball.y = old_y;
    return result;
}

bool FootballField::can_step(signed char x, signed char y){
    int new_x = ball.x + x,
        new_y = ball.y + y;
    if (FLD_POINT(new_x, new_y) != NULL && FLD_POINT(new_x, new_y)->is_wall)
        return false;
    return (FLD_POINT(new_x, new_y) == NULL) && (!(abs(x) == 1 && abs(y) == 1) || diagstep(x, y));
}

bool FootballField::diagstep(signed char x, signed char y){
    // Находим пересекаемую диагональ
    if      (x ==  1 && y ==  1)
        return can_diagstep(ball.x, ball.y + 1, ball.x + 1, ball.y);
    else if (x ==  1 && y == -1)
        return can_diagstep(ball.x + 1, ball.y, ball.x, ball.y - 1);
    else if (x == -1 && y == -1)
        return can_diagstep(ball.x, ball.y - 1, ball.x - 1, ball.y);
    else if (x == -1 && y ==  1)
        return can_diagstep(ball.x - 1, ball.y, ball.x, ball.y + 1);
    return false;
}

bool FootballField::can_diagstep(signed char bx, signed char by, signed char ex, signed char ey){
    if (FLD_POINT(bx, by) == NULL  || FLD_POINT(ex, ey) == NULL || // Если хоть одна из точек пустая
        FLD_POINT(bx, by)->is_wall || FLD_POINT(ex, ey)->is_wall)  // или является стеной
        return true;
    return !(FLD_POINT(bx, by)->include(ex, ey));
}

bool FootballField::penalty_kick(){
    if(current_step == 3){
        penalty_mode = !can_move_3x();
    }
    else {
        penalty_mode = !can_move_1x();
        if(penalty_mode){
            // You has clamped yourself!!!
            current_player *= -1;
            current_step = 3;
        }
    }
    return penalty_mode;
}

int FootballField::only_one_way(){
    int has_one = 0;
    for(int i = 1; i <= 9; i++){
        if(i == 5) continue;
        if(can_step(KEYS[i][0], KEYS[i][1])){
            if(has_one) return 0;
            has_one = i;
        }
    }
    return has_one;
}

bool FootballField::can_move_1x(){
    for(int i = 1; i <= 9; i++){
        if(i == 5) continue;
        if(can_step(KEYS[i][0], KEYS[i][1])) return true;
    }
    return false;
}

bool FootballField::can_move_3x(){
    for(int i = 1; i <= 9; i++){
        if(i == 5) continue;
        for(int j = 1; j <= 9; j++){
            if(j == 5 || j == keycontrast(i)) continue;
            for(int k = 1; k <= 9; k++){
                if(k == 5 || k == keycontrast(j)) continue;

                if(!can_step(KEYS[i][0], KEYS[i][1])) continue;

                ball.step(KEYS[i][0], KEYS[i][1]);
                if(!can_step(KEYS[j][0], KEYS[j][1])){
                    ball.step(KEYS[keycontrast(i)][0], KEYS[keycontrast(i)][1]);
                    continue;
                }

                ball.step(KEYS[j][0], KEYS[j][1]);
                bool result = can_step(KEYS[k][0], KEYS[k][1]);
                ball.step(KEYS[keycontrast(j)][0], KEYS[keycontrast(j)][1]);
                ball.step(KEYS[keycontrast(i)][0], KEYS[keycontrast(i)][1]);
                if(result) return true;
            }
        }
    }
    return false;
}
<commit_msg>Small refactor<commit_after>#include "football_field.h"
#include <QDebug>

#define keycontrast(KEY) (10 - (KEY))
#define red_win(X, Y) ((Y) == -26 && (X) <= 2 && (X) >= -2)
#define blue_win(X, Y) ((Y) == 26 && (X) <= 2 && (X) >= -2)

// Конструктор
FootballField::FootballField()
{
    // Зануляем массив.
    for(int i = 0; i < FIELD_WIDTH / PX_SCALE + 1; i++){
        for(int j = 0; j < FIELD_HEIGHT / PX_SCALE + 1; j++){
            points[i][j] = NULL;
        }
    }

    // Стартовая точка.
    FLD_POINT(0, 0) = new FPoint(0, 0);

    // Создаём ворота.
    FLD_POINT(-3, -25) = new FPoint(-3, -25, true);
    FLD_POINT( 3, -25) = new FPoint( 3, -25, true);
    FLD_POINT(-3,  25) = new FPoint(-3,  25, true);
    FLD_POINT( 3,  25) = new FPoint( 3,  25, true);

    // Создаём коробку (окружающие поле стены).
    for(int y = -26; y <= 26; y++){
        FLD_POINT(-20, y) = new FPoint(-20, y, true);
        FLD_POINT( 20, y) = new FPoint(20, y, true);
        if((y > -20 && y < -2) || (y > 2 && y < 20)){
            FLD_POINT(y,  26) = new FPoint(y, 26, true);
            FLD_POINT(y, -26) = new FPoint(y, -26, true);
        }
    }

    // Мячик изначально в позиции 0:0
    current_player = 1; // 1 (blue) -1 (red)
}

// Деструктор
FootballField::~FootballField(){
    //
    for(int i = 0; i < FIELD_WIDTH / PX_SCALE + 1; i++){
        for(int j = 0; j < FIELD_HEIGHT / PX_SCALE + 1; j++){
            delete points[i][j];
        }
    }
}

bool FootballField::try_step(int key){
    if (gameover)
        return false;

    if (penalty_mode){
        return try_penalty(key);
    }

    if (can_step(KEYS[key][0], KEYS[key][1])){
        signed char x = ball.x + KEYS[key][0],
                    y = ball.y + KEYS[key][1];
        if(red_win(x, y)){
            winner = -1;
            qDebug() << "red player winner!\n";
            gameover = true;
            show_ball = false;
        }
        if(blue_win(x, y)){
            winner = 1;
            qDebug() << "blue player winner!\n";
            gameover = true;
            show_ball = false;
        }
        if(gameover){
            steps.push_back(key * current_player);
            return true;
        }
        steps.push_back(key * current_player);
        FLD_POINT(x, y) = new FPoint(x, y);
        FLD_POINT(x, y)->push(FLD_POINT(ball.x, ball.y));
        FLD_POINT(ball.x, ball.y)->push(FLD_POINT(x, y));
        ball.step(KEYS[key][0], KEYS[key][1]);
        if(penalty_kick()){
            qDebug() << "PENALTY";
        }
        else if(current_step == 3){
            current_player *= -1;
            current_step = 1;
        }
        else
            ++current_step;

        return true;
    }
    return false;
}

bool FootballField::try_penalty(int key){
    signed char x = ball.x + KEYS[key][0],
                y = ball.y + KEYS[key][1];
    // Validates
    for(int i = 0; i < 6; i++){
        if (FLD_POINT(x, y) != NULL && FLD_POINT(x, y)->is_wall)
            return false;
        if(red_win(x, y)){
            winner = -1;
            qDebug() << "red player winner!\n";
            gameover = true;
        }
        if(blue_win(x, y)){
            winner = 1;
            qDebug() << "blue player winner!\n";
            gameover = true;
        }
        if(gameover){
            show_ball = false;
            for(; i >= 0; i--)
                steps.push_back(key * current_player);
            return true;
        }
        x += KEYS[key][0];
        y += KEYS[key][1];
    }

    // return to first point
    x = ball.x + KEYS[key][0];
    y = ball.y + KEYS[key][1];
    // Real ball moves
    for(int i = 0; i < 6; i++){
        steps.push_back(key * current_player);
        if(FLD_POINT(x, y) == NULL)
            FLD_POINT(x, y) = new FPoint(x, y);
        FLD_POINT(x, y)->push(FLD_POINT(ball.x, ball.y));
        FLD_POINT(ball.x, ball.y)->push(FLD_POINT(x, y));
        ball.step(KEYS[key][0], KEYS[key][1]);
        x += KEYS[key][0];
        y += KEYS[key][1];
    }

    if(penalty_kick()){
        qDebug() << "one more PENALTY";
    }
    else if (current_step == 3) {
        current_player *= -1;
        current_step = 1;
    }
    else
        ++current_step;
    return true;
}

bool FootballField::can_step_from(signed char x, signed char y, int bx, int by){
    const int old_x = ball.x,
              old_y = ball.y;
    ball.x = bx;
    ball.y = by;
    bool result = can_step(x, y);
    ball.x = old_x;
    ball.y = old_y;
    return result;
}

bool FootballField::can_step(signed char x, signed char y){
    int new_x = ball.x + x,
        new_y = ball.y + y;
    if (FLD_POINT(new_x, new_y) != NULL && FLD_POINT(new_x, new_y)->is_wall)
        return false;
    return (FLD_POINT(new_x, new_y) == NULL) && (!(abs(x) == 1 && abs(y) == 1) || diagstep(x, y));
}

bool FootballField::diagstep(signed char x, signed char y){
    // Находим пересекаемую диагональ
    if      (x ==  1 && y ==  1)
        return can_diagstep(ball.x, ball.y + 1, ball.x + 1, ball.y);
    else if (x ==  1 && y == -1)
        return can_diagstep(ball.x + 1, ball.y, ball.x, ball.y - 1);
    else if (x == -1 && y == -1)
        return can_diagstep(ball.x, ball.y - 1, ball.x - 1, ball.y);
    else if (x == -1 && y ==  1)
        return can_diagstep(ball.x - 1, ball.y, ball.x, ball.y + 1);
    return false;
}

bool FootballField::can_diagstep(signed char bx, signed char by, signed char ex, signed char ey){
    if (FLD_POINT(bx, by) == NULL  || FLD_POINT(ex, ey) == NULL || // Если хоть одна из точек пустая
        FLD_POINT(bx, by)->is_wall || FLD_POINT(ex, ey)->is_wall)  // или является стеной
        return true;
    return !(FLD_POINT(bx, by)->include(ex, ey));
}

bool FootballField::penalty_kick(){
    if(current_step == 3){
        penalty_mode = !can_move_3x();
    }
    else {
        penalty_mode = !can_move_1x();
        if(penalty_mode){
            // You has clamped yourself!!!
            current_player *= -1;
            current_step = 3;
        }
    }
    return penalty_mode;
}

int FootballField::only_one_way(){
    int has_one = 0;
    for(int i = 1; i <= 9; i++){
        if(i == 5) continue;
        if(can_step(KEYS[i][0], KEYS[i][1])){
            if(has_one) return 0;
            has_one = i;
        }
    }
    return has_one;
}

bool FootballField::can_move_1x(){
    for(int i = 1; i <= 9; i++){
        if(i == 5) continue;
        if(can_step(KEYS[i][0], KEYS[i][1])) return true;
    }
    return false;
}

bool FootballField::can_move_3x(){
    for(int i = 1; i <= 9; i++){
        if(i == 5) continue;
        for(int j = 1; j <= 9; j++){
            if(j == 5 || j == keycontrast(i)) continue;
            for(int k = 1; k <= 9; k++){
                if(k == 5 || k == keycontrast(j)) continue;

                if(!can_step(KEYS[i][0], KEYS[i][1])) continue;

                ball.step(KEYS[i][0], KEYS[i][1]);
                if(!can_step(KEYS[j][0], KEYS[j][1])){
                    ball.step(KEYS[keycontrast(i)][0], KEYS[keycontrast(i)][1]);
                    continue;
                }

                ball.step(KEYS[j][0], KEYS[j][1]);
                bool result = can_step(KEYS[k][0], KEYS[k][1]);
                ball.step(KEYS[keycontrast(j)][0], KEYS[keycontrast(j)][1]);
                ball.step(KEYS[keycontrast(i)][0], KEYS[keycontrast(i)][1]);
                if(result) return true;
            }
        }
    }
    return false;
}
<|endoftext|>