首页 > 技术文章 > QT

linxw-blog 2019-09-06 09:31 原文

--------------Command.h

#pragma once
#ifndef __COMMAND_H__
#define __COMMAND_H__

#include "CommandLine.h"
#include <string>


class Command {
public:

	string name;
	function<bool(CommandLine*)> callback;

	bool Execute(CommandLine *cmd);

	Command();
	Command(string _name, function<bool(CommandLine*)> _callback);
	~Command();
};
#endif
--------------Command.cpp
#include "stdafx.h"
#include "Command.h"


bool Command::Execute(CommandLine *cmd) {
	if(callback != NULL) {
		return callback(cmd);
	}
	return false;
}

Command::Command() {
	name = "";
	callback = NULL;
}

Command::Command(string _name, function<bool(CommandLine*)> _callback) {
	this->name = _name;
	this->callback = _callback;
}

Command::~Command() {
}

---------------CommandHandler。h
#pragma once

#ifndef __COMMAND_HANDLE_H__
#define __COMMAND_HANDLE_H__

#include "Command.h"
#include "TabletFilterTester.h"

#include <string>
#include <map>


class CommandHandler {
public:
	map<string, Command*> commands;
	map<string, string> aliases;
	map<string, string> aliasNames;
	map<string, string> help;

	CommandHandler();
	~CommandHandler();

	bool AddCommand(Command *command);
	bool AddAlias(string commandName, string alias);
	bool AddHelp(string commandName, string line);
	void CreateCommands();
	void CreateTabletCommands();
	void CreateFilterCommands();
	void CreateDeviceCommands();
	void CreateAuxCommands();
	void CreateOtherCommands();

	bool IsValidCommand(string command);
	bool ExecuteCommand(string command);
	bool ExecuteCommand(CommandLine *cmd);
	bool ExecuteCommand(string command, string parameters);
	bool ExecuteCommand(string command, CommandLine *cmd);

	bool ExecuteFile(string filename);

};
#endif
---------------CommandHandler。cpp
#include "stdafx.h"
#include "CommandHandler.h"

#define LOG_MODULE ""
#include "Logger.h"


//
// Constructor
//
CommandHandler::CommandHandler() {
}


//
// Destructor
//
CommandHandler::~CommandHandler() {
}



//
// Add command
//
bool CommandHandler::AddCommand(Command *command) {
    string name = command-> name;
	transform(name.begin(), name.end(), name.begin(), ::tolower);
	if(commands.count(name) <= 0) {
        commands.insert(pair<string, Command*>(name, command));
		return true;
	}
	return false;
}

//
// Add command alias
//
bool CommandHandler::AddAlias(string alias, string commandName) {

	string aliasLowerCase = alias;
	transform(aliasLowerCase.begin(), aliasLowerCase.end(), aliasLowerCase.begin(), ::tolower);
	transform(commandName.begin(), commandName.end(), commandName.begin(), ::tolower);

	if(aliases.count(aliasLowerCase) <= 0) {
		aliases.insert(pair<string, string>(aliasLowerCase, commandName));
		aliasNames.insert(pair<string, string>(aliasLowerCase, alias));
		return true;
	}

	return false;
}

//
// Add command help text
//
bool CommandHandler::AddHelp(string commandName, string line) {
	transform(commandName.begin(), commandName.end(), commandName.begin(), ::tolower);
	line.append("\n");
	if(help.count(commandName) < 0) {
		help.insert(pair<string, string>(commandName, line));
	}
	else {
		help[commandName].append(line);
	}
	return false;
}

//
// Create commands
//
void CommandHandler::CreateCommands() {

	CreateDeviceCommands();
	CreateTabletCommands();
	CreateAuxCommands();
	CreateFilterCommands();
	CreateOtherCommands();

}

//
// Is valid command?
//
bool CommandHandler::IsValidCommand(string command) {
	transform(command.begin(), command.end(), command.begin(), ::tolower);
	if(aliases.count(command) > 0) {
		command = aliases[command];
	}
	if(commands.count(command) > 0) {
		return true;
	}
	return false;
}

//
// Execute a command using command name
//
bool CommandHandler::ExecuteCommand(string command) {
	return ExecuteCommand(command, NULL);
}

//
// Execute a command using command line
//
bool CommandHandler::ExecuteCommand(CommandLine *cmd) {
	return ExecuteCommand(cmd->command, cmd);
}

//
// Execute a command using command and parameter string
//
bool CommandHandler::ExecuteCommand(string command, string parameters) {
	CommandLine *cmd = new CommandLine(command + " " + parameters);
	bool result = ExecuteCommand(command, cmd);
	delete cmd;
	return result;
}

//
// Execute a command
//
bool CommandHandler::ExecuteCommand(string command, CommandLine * cmd) {
	transform(command.begin(), command.end(), command.begin(), ::tolower);
	if(aliases.count(command) > 0) {
		command = aliases[command];
	}
	if(commands.count(command) > 0) {
		return commands[command]->Execute(cmd);
	}
	return false;
}

//
// Execute commands from a file
//
bool CommandHandler::ExecuteFile(string filename) {

	CommandLine *cmd;
	ifstream file;
	string line = "";

	// Open file
	file.open(filename);
	if(!file.is_open()) {
		return false;
	}


	LOG_INFO("\\ Reading '%s'\n", filename.c_str());

	// Loop through lines
	while(!file.eof()) {
		getline(file, line);
		if(line.length() == 0) continue;
		cmd = new CommandLine(line);

		//
		// Do not redefine tablet if one is already open
		//
		if(
			(
				cmd->is("Tablet")
				||
				cmd->is("USBTablet")
				||
				cmd->is("HIDTablet")
				)
			&&
			tablet != NULL &&
			tablet->IsConfigured()
		) {
			LOG_INFO(">> %s\n", cmd->line.c_str());
			LOG_INFO("Tablet is already defined!\n");
			delete cmd;
			break;
		}
		LOG_INFO(">> %s\n", cmd->line.c_str());

        try{
        ExecuteCommand(cmd);
        }
        catch(bad_alloc e){
            LOG_INFO("bad alloc %s\n",cmd->line.c_str());
        }

		delete cmd;
	}
	file.close();

	LOG_INFO("/ End of '%s'\n", filename.c_str());

	return true;
}

-----------CommandLine。h
#pragma once
#ifndef __COMMAND_LINE_H__
#define __COMMAND_LINE_H__
#include <string>
#include <iomanip>
#include <sstream>
#include <vector>
#include <stdlib.h>
#include <algorithm>

using namespace std;

class CommandLine {
public:
	string line;
	string command;
	vector<string> values;
	int valueCount;
	bool isValid;

	CommandLine(string text);
	~CommandLine();
	bool is(string command);
	string GetCommandLowerCase();
	string GetParameterString();
	int Parse(string text);
	string ParseHex(string str);
	string ParseBits(string str);
	string ParseHexBits(string str);
	string GetString(int index, string defaultValue);
	string GetStringLower(int index, string defaultValue);
	int GetInt(int index, int defaultValue);
	long GetLong(int index, long defaultValue);
	double GetDouble(int index, double defaultValue);
	float GetFloat(int index, float defaultValue);
	bool GetBoolean(int index, bool defaultValue);
};

#endif


-----------CommandLine。cpp
#include "stdafx.h"
#include "CommandLine.h"

#define LOG_MODULE "CommandLine"
#include "Logger.h"

//
// Constructor
//
CommandLine::CommandLine(string text) {
	this->line = text;
	this->Parse(text);
}

//
// Destructor
//
CommandLine::~CommandLine() {
}

//
// Command matcher
//
bool CommandLine::is(string command) {

	string match = this->command;
	transform(command.begin(), command.end(), command.begin(), ::tolower);
	transform(match.begin(), match.end(), match.begin(), ::tolower);

	if(command.compare(match) == 0) {
		return true;
	}
	return false;
}

//
// Get command in lower case
//
string CommandLine::GetCommandLowerCase() {
	transform(command.begin(), command.end(), command.begin(), ::tolower);
	return command;
}

//
// Get command parameters as as string
//
string CommandLine::GetParameterString() {
	if(command.size() < line.size())
		return line.substr(command.size() + 1);
	return "";
}


//
// Parse
//
int CommandLine::Parse(string line) {

	string item = "";
	vector<string> items;

	int lineLength = line.size();
	int itemLength = 0;
	int itemCount = 0;
	int index = 0;

	char currentChar;
	char previousChar = 0;
	char splitChars[] = " ,:(){}[]=";
	char endChars[] = { '\r', '\n', ';', 0 };
	char commentChar = '#';
	char escapeChar = '\\';
	char enclosingChar = '"';

	bool isSplitChar = false;
	bool isEndChar = false;
	bool isEnclosingChar = false;
	bool isLastChar = false;
	bool isEnclosed = false;

	for(std::string::iterator it = line.begin(); it != line.end(); ++it) {
		currentChar = *it;

		// Comment char
		if(!isEnclosed && currentChar == commentChar) {
			if(itemLength > 0) {
				items.push_back(item);
			}
			break;
		}

		// Is split char?
		isSplitChar = false;
		for(int i = 0; i < (int)sizeof(splitChars); i++) {
			if(splitChars[i] && currentChar == splitChars[i]) {
				isSplitChar = true;
				break;
			}
		}

		// Is end char?
		isEndChar = false;
		for(int i = 0; i < (int)sizeof(endChars); i++) {
			if(currentChar == endChars[i]) {
				isEndChar = true;
				break;
			}
		}

		// Is last char?
		isLastChar = false;
		if(index == lineLength - 1) {
			isLastChar = true;
		}


		// Toggle enclosing
		isEnclosingChar = false;
		if(currentChar == enclosingChar && previousChar != escapeChar) {
			isEnclosed = !isEnclosed;
			isEnclosingChar = true;
		}

		// New item
		if(
			!isEnclosed &&
			(
				isSplitChar ||
				isEndChar ||
				(itemCount == 0 && currentChar == '=') ||
				(itemCount == 1 && itemLength == 0 && currentChar == '=') ||
				isLastChar ||
				(isLastChar && isEnclosingChar)
				)
			) {

			//INFO("char: %c\n", currentChar);
			//INFO("itemCount = %d\n", itemCount);
			//INFO("itemLength = %d\n", itemLength);

			// Last char
			if(isLastChar && !isEndChar && !isSplitChar) {
				if(!isEnclosingChar) {
					item.push_back(currentChar);
					itemLength = 1;
				}
			}

			// Create new item
			if(itemLength > 0) {
				items.push_back(item);
				item = "";
				itemLength = 0;
				itemCount++;
			}
			else {
				item = "";
				itemLength = 0;
			}

			// Stop parsing at end of the line
			if(isEndChar) {
				break;
			}

			// Add text to item
		}
		else if(currentChar >= 32) {
			if(itemCount == 0 && currentChar == '=') {
			}
			else if(isEnclosingChar) {
			}
			else if(currentChar == escapeChar && !isEnclosed) {
			}
			else {
				item.push_back(currentChar);
				itemLength++;
			}
		}
		index++;
		previousChar = currentChar;
	}

	// Set command
	if(itemCount > 0) {
		command = items[0];
		isValid = true;
	}
	else {
		isValid = false;
	}

	// Set values
	values.clear();
	for(int i = 1; i < (int)items.size(); i++) {
		values.push_back(items[i]);
	}

	valueCount = values.size();
	return valueCount;
}


//
// Parse hex string
//
string CommandLine::ParseHex(string str) {
	if(str.size() >= 3 && str[0] == '0' && str[1] == 'x') {
		try {
			string tmp = str.substr(2, str.size() - 2);
			return to_string(stol(tmp, 0, 16));
		} catch(exception) {
		}
	}
	return str;
}

//
// Parse bit string (e.g. 0b10100101)
//
string CommandLine::ParseBits(string str) {
	if(str.size() >= 3 && str[0] == '0' && str[1] == 'b') {
		int length = str.size();
		unsigned int output = 0;
		try {
			for(int i = 2; i < length; i++) {
				char c = str.at(i);
				if(c == '1') {
					output |= 1 << (length - (i + 1));
				}
			}
			return to_string(output);
		} catch(exception) {
		}
	}
	return str;
}

//
// Parse hex and bits strings
//
string CommandLine::ParseHexBits(string str)
{
	return ParseBits(ParseHex(str));
}


//
// Get string value
//
string CommandLine::GetString(int index, string defaultValue) {
	if(index < valueCount) {
		return values[index];
	}
	return defaultValue;
}


//
// Get lowercase string value
//
string CommandLine::GetStringLower(int index, string defaultValue) {
	string str = GetString(index, defaultValue);
	transform(str.begin(), str.end(), str.begin(), ::tolower);
	return str;
}


//
// Get integer
//
int CommandLine::GetInt(int index, int defaultValue) {
	if(index < valueCount) {
		try {
			auto value = stoi(ParseHexBits(values[index]));
			return value;
		} catch(exception) {}
	}
	return defaultValue;
}


//
// Get long integer
//
long CommandLine::GetLong(int index, long defaultValue) {
	if(index < valueCount) {
		try {
			auto value = stol(ParseHexBits(values[index]));
			return value;
		} catch(exception) {}
	}
	return defaultValue;
}


//
// Get double precision floating point number
//
double CommandLine::GetDouble(int index, double defaultValue) {
	if(index < valueCount) {
		try {
			auto value = stod(ParseHexBits(values[index]));
			return value;
		} catch(exception) {}
	}
	return defaultValue;
}


//
// Get floating point number
//
float CommandLine::GetFloat(int index, float defaultValue) {
	if(index < valueCount) {
		try {
			auto value = stof(ParseHexBits(values[index]));
			return value;
		} catch(exception) {}
	}
	return defaultValue;
}


//
// Get boolean
//
bool CommandLine::GetBoolean(int index, bool defaultValue) {
	if(GetInt(index, 0) > 0) return true;
	string str = GetStringLower(index, "");
	if(str == "true") return true;
	if(str == "on") return true;
	if(str == "false") return false;
	if(str == "off") return false;
	if(str == "0") return false;
	return defaultValue;
}





推荐阅读