--------------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("
");
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'
", 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
", cmd->line.c_str());
LOG_INFO("Tablet is already defined!
");
delete cmd;
break;
}
LOG_INFO(">> %s
", cmd->line.c_str());
try{
ExecuteCommand(cmd);
}
catch(bad_alloc e){
LOG_INFO("bad alloc %s
",cmd->line.c_str());
}
delete cmd;
}
file.close();
LOG_INFO("/ End of '%s'
", 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[] = { '
', '
', ';', 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
", currentChar);
//INFO("itemCount = %d
", itemCount);
//INFO("itemLength = %d
", 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;
}