Implemented command line config overrides

You can set the file to read as the config file via the command line, like
this, assuming the program supports it:

  prog -config=file.cfg

You can also override indevidual key-value pairs in the config system
using this syntax:

  prog -Ckey=value

Both commands can be used together, and you can override multiple
key-value pairs at once. To use this feature of the ConfigUtility, it must
receive argc and argv as parameters to the Load() method.
This commit is contained in:
Kayne Ruse
2014-09-28 02:11:26 +10:00
parent 9367bd802f
commit 59e3518dd8
10 changed files with 74 additions and 30 deletions
+2 -2
View File
@@ -45,12 +45,12 @@
//Public access members //Public access members
//------------------------- //-------------------------
void ClientApplication::Init(int argc, char** argv) { void ClientApplication::Init(int argc, char* argv[]) {
std::cout << "Beginning " << argv[0] << std::endl; std::cout << "Beginning " << argv[0] << std::endl;
//load the prerequisites //load the prerequisites
ConfigUtility& config = ConfigUtility::GetSingleton(); ConfigUtility& config = ConfigUtility::GetSingleton();
config.Load("rsc\\config.cfg"); config.Load("rsc\\config.cfg", argc, argv);
//------------------------- //-------------------------
//Initialize the APIs //Initialize the APIs
+1 -1
View File
@@ -35,7 +35,7 @@
class ClientApplication: public Singleton<ClientApplication> { class ClientApplication: public Singleton<ClientApplication> {
public: public:
//public methods //public methods
void Init(int argc, char** argv); void Init(int argc, char* argv[]);
void Proc(); void Proc();
void Quit(); void Quit();
+1 -1
View File
@@ -30,7 +30,7 @@
using namespace std; using namespace std;
int main(int argc, char** argv) { int main(int argc, char* argv[]) {
try { try {
//create the singletons //create the singletons
ConfigUtility::Create(); ConfigUtility::Create();
+2 -4
View File
@@ -25,7 +25,6 @@
#include "utility.hpp" #include "utility.hpp"
#include <stdexcept> #include <stdexcept>
#include <iostream>
//------------------------- //-------------------------
//Public access members //Public access members
@@ -113,7 +112,7 @@ void LobbyMenu::Render(SDL_Surface* const screen) {
(Uint16)listBox.w, (Uint16)listBox.h (Uint16)listBox.w, (Uint16)listBox.h
}; };
r.y += i * listBox.h; r.y += i * listBox.h;
SDL_FillRect(screen, &r, SDL_MapRGB(screen->format, 255, 127, 39)); SDL_FillRect(screen, &r, SDL_MapRGB(screen->format, 49, 150, 5));
} }
//draw the server name //draw the server name
@@ -226,8 +225,7 @@ void LobbyMenu::HandleJoinResponse(ClientPacket* const argPacket) {
} }
void LobbyMenu::HandleJoinRejection(TextPacket* const argPacket) { void LobbyMenu::HandleJoinRejection(TextPacket* const argPacket) {
//TODO: Better output //TODO: Better output for join rejection
std::cerr << "Error: " << argPacket->text << std::endl;
} }
//------------------------- //-------------------------
+63 -14
View File
@@ -22,14 +22,56 @@
#include "config_utility.hpp" #include "config_utility.hpp"
#include <cstdlib> #include <cstdlib>
#include <cstring>
#include <fstream> #include <fstream>
#include <sstream>
#include <stdexcept> #include <stdexcept>
void ConfigUtility::Load(std::string fname) { void ConfigUtility::Load(std::string fname, int argc, char* argv[]) {
//clear the stored configuration //clear the stored configuration
configMap.clear(); configMap.clear();
//pass to the recursive method
configMap = Read(fname); //use the default file
if (argc < 2) {
configMap = Read(fname);
return;
}
//some variables to use
table_t redirectedFile;
table_t cmdLineParams;
char key[256], val[256];
//reading from the command line
for (int i = 1; i < argc; ++i) {
//read from a specified config file
if (!strncmp(argv[i], "-config=", 8)) {
redirectedFile = Read(argv[i] + 8);
continue;
}
//set some specific values
if (!strncmp(argv[i], "-C", 2)) {
//wipe the variables
memset(key, 0, 256);
memset(key, 0, 256);
//read the key-value pair
if (sscanf(argv[i], "-C%[^=]=%[^\0]", key, val) != 2) {
std::ostringstream os;
os << "Failed to read a command line config argument (expected -C%s=%s):" << std::endl;
os << "\targv[" << i << "]: " << argv[i] << std::endl;
os << "\tkey: " << key << std::endl;
os << "\tval: " << val << std::endl;
throw(std::runtime_error( os.str() ));
}
cmdLineParams[key] = val;
}
}
//finally, construct the final config table
configMap.insert(cmdLineParams.begin(), cmdLineParams.end());
configMap.insert(redirectedFile.begin(), redirectedFile.end());
} }
ConfigUtility::table_t ConfigUtility::Read(std::string fname) { ConfigUtility::table_t ConfigUtility::Read(std::string fname) {
@@ -38,10 +80,9 @@ ConfigUtility::table_t ConfigUtility::Read(std::string fname) {
std::ifstream is(fname); std::ifstream is(fname);
if (!is.is_open()) { if (!is.is_open()) {
std::string msg; std::ostringstream os;
msg += "Failed to open a config file: "; os << "Failed to open a config file: " << fname;
msg += fname; throw(std::runtime_error( os.str() ));
throw(std::runtime_error(msg));
} }
std::string key, val; std::string key, val;
@@ -69,15 +110,23 @@ ConfigUtility::table_t ConfigUtility::Read(std::string fname) {
getline(is, key,'='); getline(is, key,'=');
getline(is, val); getline(is, val);
//trim the strings at the start & end //eat the whitespace at the start & end
while(key.size() && isspace(*key.begin())) key.erase(0, 1); while(key.size() && isspace( *key.begin() )) {
while(val.size() && isspace(*val.begin())) val.erase(0, 1); key.erase(0, 1);
}
while(val.size() && isspace( *val.begin() )) {
val.erase(0, 1);
}
while(key.size() && isspace(*(key.end()-1))) key.erase(key.end() - 1); while(key.size() && isspace( *(key.end()-1) )) {
while(val.size() && isspace(*(val.end()-1))) val.erase(val.end() - 1); key.erase(key.end() - 1);
}
while(val.size() && isspace( *(val.end()-1) )) {
val.erase(val.end() - 1);
}
//disallow empty/wiped values //disallow empty/wiped pairs
if (key.size() == 0) { if (key.size() == 0 || val.size() == 0) {
continue; continue;
} }
+1 -1
View File
@@ -29,7 +29,7 @@
class ConfigUtility : public Singleton<ConfigUtility> { class ConfigUtility : public Singleton<ConfigUtility> {
public: public:
void Load(std::string fname); void Load(std::string fname, int argc = 0, char* argv[] = nullptr);
//convert to a type //convert to a type
std::string& String(std::string); std::string& String(std::string);
+1 -1
View File
@@ -30,7 +30,7 @@
using namespace std; using namespace std;
int main(int argc, char** argv) { int main(int argc, char* argv[]) {
try { try {
//create the singletons //create the singletons
AccountManager::Create(); AccountManager::Create();
+1 -1
View File
@@ -47,7 +47,7 @@
class ServerApplication: public Singleton<ServerApplication> { class ServerApplication: public Singleton<ServerApplication> {
public: public:
//public methods //public methods
void Init(int argc, char** argv); void Init(int argc, char* argv[]);
void Proc(); void Proc();
void Quit(); void Quit();
+2 -2
View File
@@ -34,12 +34,12 @@
//public methods //public methods
//------------------------- //-------------------------
void ServerApplication::Init(int argc, char** argv) { void ServerApplication::Init(int argc, char* argv[]) {
//NOTE: I might need to rearrange the init process so that lua & SQL can interact with the map system as needed. //NOTE: I might need to rearrange the init process so that lua & SQL can interact with the map system as needed.
std::cout << "Beginning " << argv[0] << std::endl; std::cout << "Beginning " << argv[0] << std::endl;
//load the prerequisites //load the prerequisites
config.Load("rsc\\config.cfg"); config.Load("rsc\\config.cfg", argc, argv);
//------------------------- //-------------------------
//Initialize the APIs //Initialize the APIs
-3
View File
@@ -1,6 +1,3 @@
TODO: Config switch for the debug output
TODO: A better way of handling the disconnection message
TODO: LobbyMenu::HandleJoinRejection()
TODO: Get the rooms working, even if only via hotkeys TODO: Get the rooms working, even if only via hotkeys
TODO: Fix shoddy movement TODO: Fix shoddy movement
TODO: Move the statistics into their own SQL table, instead of duplicating the structure a dozen times TODO: Move the statistics into their own SQL table, instead of duplicating the structure a dozen times