source/code/common.cc
browsing at commit = 444cec0742a60eef8b4d24ebeca19fe311a4f0c5
/*
===========================================================================
blockattack - Block Attack - Rise of the Blocks
Copyright (C) 2005-2012 Poul Sander
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/
Source information and contacts persons can be found at
http://blockattack.sf.net
===========================================================================
*/
#include "common.h"
#include <sstream>
static stringstream converter;
//Function to convert numbers to string
string itoa(int num)
{
converter.str(std::string());
converter.clear();
converter << num;
return converter.str();
}
string double2str(double num)
{
converter.str(std::string());
converter.clear();
converter << num;
return converter.str();
}
/**
* str2double parses a string and returns a double with the value of the string.
* if the string is not a double then 0.0 is returned instead of throing an error
* in that way this function will always return a useable value.
*/
double str2double(string str2parse)
{
try
{
converter.clear();
converter.str(str2parse);
double val = 0.0;
converter >> val;
return val;
}
catch(ios_base::failure f)
{
return 0.0;
}
}
/**
* str2int parses a string and returns an int with the value of the string.
* if the string is not an int then 0 is returned instead of throing an error
* in that way this function will always return a useable value.
*/
int str2int(string str2parse)
{
try
{
converter.clear();
converter.str(str2parse);
int val = 0;
converter >> val;
return val;
}
catch(ios_base::failure f)
{
return 0;
}
}
#ifdef WIN32
//Returns path to "my Documents" in windows:
string getMyDocumentsPath()
{
TCHAR pszPath[MAX_PATH];
//if (SUCCEEDED(SHGetSpecialFolderPath(NULL, pszPath, CSIDL_PERSONAL, FALSE))) {
if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, pszPath)))
{
// pszPath is now the path that you want
#if DEBUG
cout << "MyDocuments Located: " << pszPath << endl;
#endif
string theResult= pszPath;
return theResult;
}
else
{
cout << "Warning: My Documents not found!" << endl;
string theResult ="";
return theResult;
}
}
#endif
/**
* Returns the path to where all settings must be saved.
* On unix-like systems this is the home-folder under: ~/.gamesaves/GAMENAME
* In Windows it is My Documents/My Games
* Consider changing this for Vista that has a special save games folder
*/
string getPathToSaveFiles()
{
#ifdef __unix__
return (string)getenv("HOME")+(string)"/.gamesaves/"+GAMENAME;
#elif WIN32
return getMyDocumentsPath()+(string)"/My Games/"+GAMENAME;
#else
return ".";
#endif
}
/**
* Takes a number of milliseconds and returns the value in commonTime format.
*/
commonTime TimeHandler::ms2ct(unsigned int milliseconds)
{
commonTime ct;
ct.days = 0;
unsigned int time = milliseconds;
ct.hours = time/(1000*60*60);
time = time % (1000*60*60);
ct.minutes = time/(1000*60);
time = time % (1000*60);
ct.seconds = time/1000;
return ct;
}
commonTime TimeHandler::getTime(string name)
{
commonTime ct;
ct.days = Config::getInstance()->getInt(name+"Days");
ct.hours = Config::getInstance()->getInt(name+"Hours");
ct.minutes = Config::getInstance()->getInt(name+"Minutes");
ct.seconds = Config::getInstance()->getInt(name+"Seconds");
return ct;
}
/**
* Returns the total runtime with toAdd added but without writing it to config file.
* Used for stats
*/
commonTime TimeHandler::peekTime(string name, commonTime toAdd)
{
commonTime ct = getTime(name);
ct.seconds +=toAdd.seconds;
ct.minutes +=ct.seconds/60;
ct.seconds = ct.seconds%60;
ct.minutes += toAdd.minutes;
ct.hours += ct.minutes/60;
ct.minutes = ct.minutes%60;
ct.hours += toAdd.hours;
ct.days += ct.hours/24;
ct.hours = ct.hours%24;
ct.days += toAdd.days;
return ct;
}
/**
* Same as peekTotalTime but writes the time to the config file.
* Should only be called only once! when the program shuts down
*/
commonTime TimeHandler::addTime(string name, commonTime toAdd)
{
commonTime ct = peekTime(name,toAdd);
Config::getInstance()->setInt(name+"Days",ct.days);
Config::getInstance()->setInt(name+"Hours",ct.hours);
Config::getInstance()->setInt(name+"Minutes",ct.minutes);
Config::getInstance()->setInt(name+"Seconds",ct.seconds);
return ct;
}
Config* Config::instance = 0;
Config::Config()
{
configMap.clear();
load();
shuttingDown = 0; // Not shutting down
}
void Config::load()
{
string filename = getPathToSaveFiles()+"/configFile";
ifstream inFile(filename.c_str());
string key;
string previuskey;
char value[MAX_VAR_LENGTH];
if(inFile)
{
while(!inFile.eof())
{
inFile >> key;
if(key==previuskey) //the last entry will be read 2 times if a linebreak is missing in the end
continue;
previuskey = key;
inFile.get(); //Read the space between the key and the content
inFile.getline(value,MAX_VAR_LENGTH);
#if DEBUG
cout << "Config "<< "read: " << key << " with:\"" << value << "\"" << endl;
#endif
configMap[key] = (string)value;
}
inFile.close();
}
}
Config* Config::getInstance()
{
if(Config::instance==0)
{
Config::instance = new Config();
}
return Config::instance;
}
void Config::save()
{
string filename = getPathToSaveFiles()+"/configFile";
ofstream outFile(filename.c_str(),ios::trunc);
if(outFile)
{
map<string,string>::iterator iter;
for(iter = configMap.begin(); iter != configMap.end(); iter++)
{
outFile << iter->first << " " << iter->second << endl;
}
outFile << "\n"; //The last entry in the file will be read double if a linebreak is missing
//This is checked on load too in case a user changes it himself.
}
outFile.close();
}
bool Config::exists(string varName) const
{
//Using that find returns an iterator to the end of the map if not found
return configMap.find(varName) != configMap.end();
}
void Config::setDefault(string varName,string content)
{
if(exists(varName))
return; //Already exists do not change
setString(varName,content);
}
void Config::setShuttingDown(long shuttingDown)
{
this->shuttingDown = shuttingDown;
}
long Config::isShuttingDown() const
{
return shuttingDown;
}
void Config::setString(string varName, string content)
{
configMap[varName] = content;
}
void Config::setInt(string varName, int content)
{
configMap[varName] = itoa(content);
}
void Config::setValue(string varName,double content)
{
configMap[varName] = double2str(content);
}
string Config::getString(string varName)
{
if(exists(varName))
{
return configMap[varName];
}
else
return "";
}
int Config::getInt(string varName)
{
if(exists(varName))
{
return str2int(configMap[varName]);
}
else
return 0;
}
double Config::getValue(string varName)
{
if(exists(varName))
{
return str2double(configMap[varName]);
}
else
return 0.0;
}