MegaGlest/source/shared_lib/sources/platform/common/platform_common.cpp

2381 lines
82 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ==============================================================
//This file is part of Glest Shared Library (www.glest.org)
//Copyright (C) 2005 Matthias Braun <matze@braunis.de>
//You can redistribute this code 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.
#ifdef WIN32
#include <winsock2.h>
#include <winsock.h>
#endif
#include "platform_common.h"
#include "cache_manager.h"
#ifdef WIN32
#include <io.h>
#include <dbghelp.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <direct.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
#if __cplusplus > 199711L
#include <chrono>
#else
#include <time.h>
#endif
#ifdef WIN32
#define S_ISDIR(mode) (((mode) & _S_IFDIR) == _S_IFDIR)
#elif defined(__GNUC__)
#else
#error "Your compiler needs to support S_IFDIR!"
#endif
#include <iostream>
#include <sstream>
#include <cassert>
#include <glob.h>
#include <errno.h>
#include <string.h>
#include <SDL.h>
#include "util.h"
#include "conversion.h"
#include "leak_dumper.h"
#include "sdl_private.h"
#include "window.h"
#include "noimpl.h"
#include "checksum.h"
#include "socket.h"
#include <algorithm>
#include <map>
#include "randomgen.h"
#include <algorithm>
#include "platform_util.h"
#include "utf8.h"
#include "byte_order.h"
#if _BSD_SOURCE || _SVID_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#endif
#ifdef __APPLE__
#include <mach-o/dyld.h>
#include <sys/param.h>
#endif
#include "leak_dumper.h"
using namespace Shared::Platform;
using namespace Shared::Util;
using namespace std;
#define _DISABLE_MEMORY_VAULT_CHECKS 1
namespace Shared { namespace PlatformCommon {
const time_t REFRESH_CRC_DAY_SECONDS = 60 * 60 * 24;
static string crcCachePath = "";
static string gameVersion = "";
static string gameGITVersion = "";
namespace Private {
bool shouldBeFullscreen = false;
int ScreenWidth = 800;
int ScreenHeight = 600;
}
/*
A thread safe localtime proxy
*/
tm threadsafe_localtime(const time_t &time) {
tm tm_snapshot;
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
localtime_s(&tm_snapshot, &time);
#else
localtime_r(&time, &tm_snapshot); // POSIX
#endif
return tm_snapshot;
}
// extracting std::time_t from std:chrono for "now"
time_t systemtime_now() {
#if __cplusplus > 199711L
system_time_point system_now = std::chrono::system_clock::now();
return std::chrono::system_clock::to_time_t(system_now);
#else
return time(NULL);
#endif
}
// =====================================
// PerformanceTimer
// =====================================
void PerformanceTimer::init(float fps, int maxTimes) {
this->times = 0;
this->maxTimes = maxTimes;
this->lastTicks = SDL_GetTicks();
this->updateTicks = static_cast<int>(1000.0f / fps);
}
bool PerformanceTimer::isTime() {
Uint32 thisTicks = SDL_GetTicks();
if((thisTicks - lastTicks) >= updateTicks &&
times < maxTimes) {
lastTicks += updateTicks;
times++;
return true;
}
times = 0;
return false;
}
void PerformanceTimer::reset() {
lastTicks = SDL_GetTicks();
}
// =====================================
// Chrono
// =====================================
Chrono::Chrono(bool autoStart) {
freq = 1000;
stopped = true;
accumCount = 0;
lastStartCount = 0;
lastTickCount = 0;
lastResult = 0;
lastMultiplier = 0;
lastStopped = false;
startCount = 0;
if(autoStart == true) {
start();
}
}
bool Chrono::isStarted() const {
return (stopped == false);
}
void Chrono::start() {
stopped = false;
startCount = SDL_GetTicks();
}
void Chrono::stop() {
Uint32 endCount = SDL_GetTicks();
accumCount += endCount - startCount;
stopped = true;
}
void Chrono::reset() {
accumCount = 0;
lastStartCount = 0;
lastTickCount = 0;
lastResult = 0;
lastMultiplier = 0;
startCount = SDL_GetTicks();
}
int64 Chrono::getMicros() {
return queryCounter(1000000);
}
int64 Chrono::getMillis() {
return queryCounter(1000);
}
int64 Chrono::getSeconds() {
return queryCounter(1);
}
int64 Chrono::queryCounter(int64 multiplier) {
if( multiplier == lastMultiplier &&
stopped == lastStopped &&
lastStartCount == startCount) {
if(stopped == true) {
return lastResult;
}
else {
Uint32 endCount = SDL_GetTicks();
if(lastTickCount == endCount) {
return lastResult;
}
}
}
int64 result = 0;
if(stopped == true) {
result = multiplier * accumCount / freq;
}
else {
Uint32 endCount = SDL_GetTicks();
result = multiplier * (accumCount + endCount - startCount) / freq;
lastTickCount = endCount;
}
lastStartCount = startCount;
lastResult = result;
lastMultiplier = multiplier;
lastStopped = stopped;
return result;
}
int64 Chrono::getCurMillis() {
return SDL_GetTicks();
}
int64 Chrono::getCurTicks() {
return SDL_GetTicks();
}
// =====================================
// Misc
// =====================================
void Tokenize(const string& str,vector<string>& tokens,const string& delimiters) {
/*
// Skip delimiters at beginning.
string::size_type lastPos = str.find_first_not_of(delimiters, 0);
// Find first "non-delimiter".
string::size_type pos = str.find_first_of(delimiters, lastPos);
while (string::npos != pos || string::npos != lastPos) {
// Found a token, add it to the vector.
tokens.push_back(str.substr(lastPos, pos - lastPos));
// Skip delimiters. Note the "not_of"
lastPos = str.find_first_not_of(delimiters, pos);
// Find next "non-delimiter"
pos = str.find_first_of(delimiters, lastPos);
}
*/
// Assume textLine contains the line of text to parse.
string textLine = str;
size_t pos = 0;
while( true ) {
size_t nextPos = textLine.find( delimiters, pos );
if( nextPos == textLine.npos ) {
tokens.push_back(textLine.substr(pos, textLine.length( )));
break;
}
tokens.push_back( string( textLine.substr( pos, nextPos - pos ) ) );
pos = nextPos + delimiters.size();
}
}
void findDirs(string path, vector<string> &results, bool errorOnNotFound,bool keepDuplicates) {
results.clear();
string currentPath = path;
endPathWithSlash(currentPath);
string searchpath = currentPath + "*.";
vector<string> current_results;
findAll(searchpath, current_results, false, errorOnNotFound);
if(current_results.empty() == false) {
for(unsigned int folder_index = 0; folder_index < current_results.size(); folder_index++) {
const string current_folder = current_results[folder_index];
const string current_folder_path = currentPath + current_folder;
if(isdir(current_folder_path.c_str()) == true) {
if(keepDuplicates == true || std::find(results.begin(),results.end(),current_folder) == results.end()) {
results.push_back(current_folder);
}
}
}
}
std::sort(results.begin(),results.end());
}
void findDirs(const vector<string> &paths, vector<string> &results, bool errorOnNotFound,bool keepDuplicates) {
results.clear();
size_t pathCount = paths.size();
for(unsigned int idx = 0; idx < pathCount; idx++) {
string currentPath = paths[idx];
endPathWithSlash(currentPath);
string path = currentPath + "*.";
vector<string> current_results;
findAll(path, current_results, false, errorOnNotFound);
if(current_results.empty() == false) {
for(unsigned int folder_index = 0; folder_index < current_results.size(); folder_index++) {
const string current_folder = current_results[folder_index];
const string current_folder_path = currentPath + current_folder;
if(isdir(current_folder_path.c_str()) == true) {
if(keepDuplicates == true || std::find(results.begin(),results.end(),current_folder) == results.end()) {
results.push_back(current_folder);
}
}
}
}
}
std::sort(results.begin(),results.end());
}
void findAll(const vector<string> &paths, const string &fileFilter, vector<string> &results, bool cutExtension, bool errorOnNotFound, bool keepDuplicates) {
results.clear();
size_t pathCount = paths.size();
for(unsigned int idx = 0; idx < pathCount; idx++) {
string currentPath = paths[idx];
endPathWithSlash(currentPath);
string path = currentPath + fileFilter;
vector<string> current_results;
findAll(path, current_results, cutExtension, errorOnNotFound);
if(current_results.empty() == false) {
for(unsigned int folder_index = 0; folder_index < current_results.size(); folder_index++) {
string current_file = current_results[folder_index];
if(keepDuplicates == true || std::find(results.begin(),results.end(),current_file) == results.end()) {
results.push_back(current_file);
}
}
}
}
std::sort(results.begin(),results.end());
}
//finds all filenames like path and stores them in results
void findAll(const string &path, vector<string> &results, bool cutExtension, bool errorOnNotFound) {
results.clear();
std::string mypath = path;
/** Stupid win32 is searching for all files without extension when *. is
* specified as wildcard
*/
if((int)mypath.size() >= 2 && mypath.compare(max((int)0,(int)mypath.size() - 2), 2, "*.") == 0) {
mypath = mypath.substr(0, max((int)0,(int)mypath.size() - 2));
mypath += "*";
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,mypath.c_str());
glob_t globbuf;
int res = glob(mypath.c_str(), 0, 0, &globbuf);
if(res < 0 && errorOnNotFound == true) {
if(errorOnNotFound) {
std::stringstream msg;
msg << "#1 Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw megaglest_runtime_error(msg.str());
}
}
else {
for(int i = 0; i < (int)globbuf.gl_pathc; ++i) {
const char* p = globbuf.gl_pathv[i];
const char* begin = p;
for( ; *p != 0; ++p) {
// strip the path component
if(*p == '/')
begin = p+1;
}
if(!(strcmp(".", begin)==0 || strcmp("..", begin)==0 || strcmp(".git", begin)==0)) {
results.push_back(begin);
}
else {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] SKIPPED SPECIAL FILENAME [%s]\n",__FILE__,__FUNCTION__,__LINE__,begin);
}
}
globfree(&globbuf);
if(results.empty() == true && errorOnNotFound == true) {
throw megaglest_runtime_error("No files found in: " + mypath);
}
if(cutExtension) {
for (size_t i=0; i<results.size(); ++i){
results.at(i)=cutLastExt(results.at(i));
}
}
}
}
bool isdir(const char *path)
{
string friendly_path = path;
#ifdef WIN32
replaceAll(friendly_path, "/", "\\");
if(EndsWith(friendly_path, "\\") == true) {
friendly_path.erase(friendly_path.begin() + friendly_path.length() -1);
}
#endif
#ifdef WIN32
#if defined(__MINGW32__)
struct _stat stats;
#else
struct _stat64i32 stats;
#endif
int result = _wstat(utf8_decode(friendly_path).c_str(), &stats);
#else
struct stat stats;
int result = stat(friendly_path.c_str(), &stats);
#endif
bool ret = (result == 0);
if(ret == true) {
ret = S_ISDIR(stats.st_mode); // #define S_ISDIR(mode) ((mode) & _S_IFDIR)
if(ret == false) {
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] path [%s] ret = %d\n",__FILE__,__FUNCTION__,__LINE__,friendly_path.c_str(),ret);
}
}
else {
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] path [%s] ret = %d, result = %d, errno = %d\n",__FILE__,__FUNCTION__,__LINE__,friendly_path.c_str(),ret,result,errno);
}
//if(ret == false) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] NOT a path [%s]\n",__FILE__,__FUNCTION__,__LINE__,path);
return ret;
}
bool fileExists(const string &path) {
if (path.size() == 0) return false;
#ifdef WIN32
wstring wstr = utf8_decode(path);
FILE* file= _wfopen(wstr.c_str(), L"rb");
#else
FILE* file= fopen(path.c_str(), "rb");
#endif
if(file != NULL) {
fclose(file);
return true;
}
// else {
//int fileErrno = errno;
//#ifdef WIN32
//int fileErrno = errno;
//DWORD error = GetLastError();
//string strError = "[#6] Could not open file, result: " + intToStr(error) + " - " + intToStr(fileErrno) + " " + strerror(fileErrno) + " [" + path + "]";
//#endif
// }
return false;
}
void removeFolder(const string &path) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] path [%s]\n",__FILE__,__FUNCTION__,__LINE__,path.c_str());
string deletePath = path;
endPathWithSlash(deletePath);
deletePath += "{,.}*";
vector<string> results = getFolderTreeContentsListRecursively(deletePath, "", true);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] path [%s] results.size() = %d\n",__FILE__,__FUNCTION__,__LINE__,path.c_str(),results.size());
// First delete files
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] DELETE FILES\n",__FILE__,__FUNCTION__,__LINE__);
for(int i = (int)results.size() -1; i >= 0; --i) {
string item = results[i];
//if(item.find(".git") != string::npos) {
// printf("!!!!!!!!!!!!!!!!!! FOUND SPECIAL FOLDER [%s] in [%s]\n",item.c_str(),path.c_str());
//}
if(isdir(item.c_str()) == false) {
bool result = removeFile(item);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] fileitem [%s] result = %d\n",__FILE__,__FUNCTION__,__LINE__,item.c_str(),result);
}
}
// Now delete folders
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] DELETE FOLDERS\n",__FILE__,__FUNCTION__,__LINE__);
for(int i = (int)results.size() -1; i >= 0; --i) {
string item = results[i];
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] item [%s] isdir(item.c_str()) = %d\n",__FILE__,__FUNCTION__,__LINE__,item.c_str(), isdir(item.c_str()));
if(isdir(item.c_str()) == true) {
//printf("~~~~~ REMOVE FOLDER [%s] in [%s]\n",item.c_str(),path.c_str());
#ifdef WIN32
//int result = _rmdir(item.c_str());
int result = _wrmdir(utf8_decode(item).c_str());
#else
int result = rmdir(item.c_str());
#endif
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] item [%s] result = %d\n",__FILE__,__FUNCTION__,__LINE__,item.c_str(),result);
if(result != 0 && item != path) {
printf("CANNOT REMOVE FOLDER [%s] in [%s]\n",item.c_str(),path.c_str());
removeFolder(item);
}
}
}
#ifdef WIN32
//int result = _rmdir(path.c_str());
int result = _wrmdir(utf8_decode(path).c_str());
#else
int result = rmdir(path.c_str());
#endif
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] path [%s] result = %d\n",__FILE__,__FUNCTION__,__LINE__,path.c_str(),result);
}
bool StartsWith(const std::string &str, const std::string &key) {
return str.find(key) == 0;
}
bool EndsWith(const string &str, const string& key)
{
bool result = false;
if (str.length() >= key.length()) {
result = (0 == str.compare(max((int)0,(int)str.length() - (int)key.length()), key.length(), key));
}
return result;
}
void endPathWithSlash(string &path,bool requireOSSlash) {
if(EndsWith(path, "/") == false && EndsWith(path, "\\") == false) {
string seperator = "/";
if(requireOSSlash == true) {
#if defined(WIN32)
seperator = "\\";
#endif
}
path += seperator;
}
}
string formatPath(string path) {
replaceAll(path, "\"", "");
replaceAll(path, "//", "/");
return path;
}
void trimPathWithStartingSlash(string &path) {
if(StartsWith(path, "/") == true || StartsWith(path, "\\") == true) {
path.erase(path.begin(),path.begin()+1);
//printf("************* trimPathWithStartingSlash changed path [%s]\n",path.c_str());
}
}
void updatePathClimbingParts(string &path,bool processPreviousDirTokenCheck) {
// Update paths with /./
string::size_type pos = path.find("/./");
if(pos != string::npos && pos != 0) {
string orig = path;
path.erase(pos,2);
//pos--;
//printf("#1 CHANGE relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
pos = path.find("/./");
if(pos != string::npos && pos != 0) {
updatePathClimbingParts(path, processPreviousDirTokenCheck);
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("CHANGED relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
}
pos = path.find("\\.\\");
if(pos != string::npos && pos != 0) {
string orig = path;
path.erase(pos,2);
//pos--;
//printf("#w CHANGE relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
pos = path.find("\\.\\");
if(pos != string::npos && pos != 0) {
updatePathClimbingParts(path, processPreviousDirTokenCheck);
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("CHANGED relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
}
// Update paths with ..
if(processPreviousDirTokenCheck) {
pos = path.find("..");
if(pos != string::npos && pos != 0) {
string orig = path;
if(path[pos-1] != ' ' || (path.length() > 2 && path[pos+2] != ' ')) {
path.erase(pos,2);
//printf("#3 [%d] CHANGE relative path from [%s] to [%s]\n",(int)pos,orig.c_str(),path.c_str());
pos--;
//pos = pos -1;
//printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #3b [%d]\n",(int)pos);
if(path[pos] == '/' || path[pos] == '\\') {
path.erase(pos,1);
//printf("#4 CHANGE relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
}
for(int x = (int)pos; x >= 0; --x) {
//printf("x [%d][%c] pos [%ld][%c] [%s]\n",x,path[x],(long int)pos,path[pos],path.substr(0,x+1).c_str());
if((path[x] == '/' || path[x] == '\\') && x != (int)pos) {
//string origLoop = path;
path.erase(x,(int)pos-x);
//printf("#5 [%d] [%d] [%d] CHANGE relative path from [%s] to [%s]\n",(int)pos,(int)x,(int)origLoop.length(),origLoop.c_str(),path.c_str());
break;
}
}
pos = path.find("..");
}
else {
//printf("#6a [%d]\n",(int)pos);
//pos = path.find("..",pos+1);
pos = string::npos;
//printf("#6b [%d]\n",(int)pos);
}
if(pos != string::npos && pos != 0) {
updatePathClimbingParts(path,processPreviousDirTokenCheck);
}
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("CHANGED relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
}
}
/*
string::size_type pos = path.rfind("..");
if(pos != string::npos && pos != 0) {
string orig = path;
path.erase(pos,2);
pos--;
if(path[pos] == '/' || path[pos] == '\\') {
path.erase(pos,1);
}
for(int x = pos; x >= 0; --x) {
//printf("x [%d][%c] pos [%ld][%c] [%s]\n",x,path[x],(long int)pos,path[pos],path.substr(0,x+1).c_str());
if((path[x] == '/' || path[x] == '\\') && x != pos) {
path.erase(x,pos-x);
break;
}
}
printf("CHANGED relative path from [%s] to [%s]\n",orig.c_str(),path.c_str());
}
*/
}
string getCRCCacheFilePath() {
return crcCachePath;
}
void setCRCCacheFilePath(string path) {
crcCachePath = path;
}
string getGameVersion() {
return gameVersion;
}
string getGameGITVersion() {
return gameGITVersion;
}
void setGameVersion(string version) {
gameVersion = version;
}
void setGameGITVersion(string git) {
gameGITVersion = git;
}
string getCRCCacheFileName(std::pair<string,string> cacheKeys) {
string crcCacheFile = cacheKeys.first + cacheKeys.second;
return crcCacheFile;
}
string getFormattedCRCCacheFileName(std::pair<string,string> cacheKeys) {
string crcCacheFile = getCRCCacheFileName(cacheKeys);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] cacheKeys.first = [%s] cacheKeys.second [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,cacheKeys.first.c_str(),cacheKeys.second.c_str());
Checksum checksum;
checksum.addString(crcCacheFile);
string result = getCRCCacheFilePath() + "CRC_CACHE_" + uIntToStr(checksum.getSum());
return result;
}
std::pair<string,string> getFolderTreeContentsCheckSumCacheKey(vector<string> paths, string pathSearchString, const string &filterFileExt) {
string cacheLookupId = CacheManager::getFolderTreeContentsCheckSumRecursivelyCacheLookupKey1;
string cacheKey = "";
for(unsigned int idx = 0; idx < paths.size(); ++idx) {
string path = paths[idx] + pathSearchString;
cacheKey += path + "_" + filterFileExt + "_";
}
return make_pair(cacheLookupId,cacheKey);
}
pair<bool,time_t> hasCachedFileCRCValue(string crcCacheFile, uint32 &value) {
//bool result = false;
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] Line: %d for Cache file [%s]\n",__FILE__,__FUNCTION__,__LINE__,crcCacheFile.c_str());
}
pair<bool,time_t> result = make_pair(false,0);
if(fileExists(crcCacheFile) == true) {
#ifdef WIN32
FILE *fp = _wfopen(utf8_decode(crcCacheFile).c_str(), L"r");
#else
FILE *fp = fopen(crcCacheFile.c_str(),"r");
#endif
if(fp != NULL) {
time_t refreshDate = 0;
uint32 crcValue = 0;
time_t lastUpdateDate = 0;
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] Line: %d for Cache file [%s]\n",__FILE__,__FUNCTION__,__LINE__,crcCacheFile.c_str());
}
char gameVer[500]="";
char gitVer[500]="";
char actualFilePath[8096]="";
int readbytes = fscanf(fp,"%20ld,%20u,%20ld\n%499s\n%499s\n%8095s",
&refreshDate,
&crcValue,
&lastUpdateDate,
&gameVer[0],
&gitVer[0],
&actualFilePath[0]);
refreshDate = Shared::PlatformByteOrder::fromCommonEndian(refreshDate);
crcValue = Shared::PlatformByteOrder::fromCommonEndian(crcValue);
lastUpdateDate = Shared::PlatformByteOrder::fromCommonEndian(lastUpdateDate);
string readGameVer = Shared::PlatformByteOrder::fromCommonEndian(string(gameVer));
string readGitVer = Shared::PlatformByteOrder::fromCommonEndian(string(gitVer));
string readActualFilePath = Shared::PlatformByteOrder::fromCommonEndian(string(actualFilePath));
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("CRC readGameVer [%s] [%s]\n%s\n",readGameVer.c_str(),readGitVer.c_str(),readActualFilePath.c_str());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] Line: %d for Cache file [%s] readbytes = %d\n",__FILE__,__FUNCTION__,__LINE__,crcCacheFile.c_str(),readbytes);
}
fclose(fp);
struct tm future; /* as in future date */
future.tm_sec = 0;
future.tm_min = 0;
future.tm_hour = 0;
future.tm_mday = 6; /* 1st */
future.tm_mon = 6; /* July */
future.tm_year = 2012 - 1900; /* 2038 in years since 1900 */
future.tm_isdst = 0; /* Daylight Saving not in affect (UTC) */
#ifdef _BSD_SOURCE
future.tm_zone = "UTC";
#endif
time_t tBadCRCDate = mktime( &future );
result.second = lastUpdateDate;
if( readGameVer != "" && readGitVer != "" &&
refreshDate > 0 &&
refreshDate > tBadCRCDate &&
time(NULL) < refreshDate) {
result.first = true;
value = crcValue;
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) {
//struct tm *loctime = localtime (&refreshDate);
struct tm loctime = threadsafe_localtime(refreshDate);
char szBuf1[100]="";
strftime(szBuf1,100,"%Y-%m-%d %H:%M:%S",&loctime);
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"=-=-=-=- READ CACHE for Cache file [%s] refreshDate = %ld [%s], crcValue = %u\n",
crcCacheFile.c_str(),refreshDate, szBuf1, crcValue);
}
}
else {
//time_t now = time(NULL);
//struct tm *loctime = localtime (&now);
struct tm loctime = threadsafe_localtime(systemtime_now());
char szBuf1[100]="";
strftime(szBuf1,100,"%Y-%m-%d %H:%M:%S",&loctime);
loctime = threadsafe_localtime(refreshDate);
char szBuf2[100]="";
strftime(szBuf2,100,"%Y-%m-%d %H:%M:%S",&loctime);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,
"=-=-=-=- NEED TO CALCULATE CRC for Cache file [%s] now = %ld [%s], refreshDate = %ld [%s], crcValue = %u\n",
crcCacheFile.c_str(), systemtime_now(), szBuf1, refreshDate, szBuf2, crcValue);
}
}
}
else {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"FILE NOT FOUND(1) for Cache file [%s]\n",crcCacheFile.c_str());
}
}
}
else {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"FILE NOT FOUND(2) for Cache file [%s]\n",crcCacheFile.c_str());
}
}
return result;
}
void writeCachedFileCRCValue(string crcCacheFile, uint32 &crcValue, string actualFileName) {
#ifdef WIN32
FILE *fp = _wfopen(utf8_decode(crcCacheFile).c_str(), L"w");
#else
FILE *fp = fopen(crcCacheFile.c_str(),"w");
#endif
if(fp != NULL) {
//RandomGen random;
//int offset = random.randRange(5, 15);
srand((unsigned int)time(NULL) + (unsigned long)crcCacheFile.length());
int offset = rand() % 15;
if(offset == 0) {
offset = 3;
}
time_t now = time(NULL);
time_t refreshDate = now + (REFRESH_CRC_DAY_SECONDS * offset);
//struct tm *loctime = localtime (&refreshDate);
struct tm loctime = threadsafe_localtime(refreshDate);
char szBuf1[100]="";
strftime(szBuf1,100,"%Y-%m-%d %H:%M:%S",&loctime);
string writeGameVer = Shared::PlatformByteOrder::toCommonEndian(gameVersion);
string writeGameGITVersion = Shared::PlatformByteOrder::toCommonEndian(gameGITVersion);
string writeActualFileName = Shared::PlatformByteOrder::toCommonEndian(actualFileName);
fprintf(fp,"%20ld,%20u,%20ld",
Shared::PlatformByteOrder::toCommonEndian(refreshDate),
Shared::PlatformByteOrder::toCommonEndian(crcValue),
Shared::PlatformByteOrder::toCommonEndian(now));
fprintf(fp,"\n%s\n%s\n%s",
writeGameVer.c_str(),
writeGameGITVersion.c_str(),
writeActualFileName.c_str());
fclose(fp);
//if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"========== Writing CRC Cache offset [%d] refreshDate = %ld [%s], crcValue = %u, file [%s]\n",offset,refreshDate,szBuf1,crcValue,crcCacheFile.c_str());
}
}
void clearFolderTreeContentsCheckSum(vector<string> paths, string pathSearchString, const string &filterFileExt) {
std::pair<string,string> cacheKeys = getFolderTreeContentsCheckSumCacheKey(paths, pathSearchString, filterFileExt);
string cacheLookupId = cacheKeys.first;
std::map<string,uint32> &crcTreeCache = CacheManager::getCachedItem< std::map<string,uint32> >(cacheLookupId);
string cacheKey = cacheKeys.second;
if(crcTreeCache.find(cacheKey) != crcTreeCache.end()) {
crcTreeCache.erase(cacheKey);
}
for(unsigned int idx = 0; idx < paths.size(); ++idx) {
string path = paths[idx];
clearFolderTreeContentsCheckSum(path, filterFileExt);
}
string crcCacheFile = getFormattedCRCCacheFileName(cacheKeys);
if(fileExists(crcCacheFile) == true) {
bool result = removeFile(crcCacheFile);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] fileitem [%s] result = %d\n",__FILE__,__FUNCTION__,__LINE__,crcCacheFile.c_str(),result);
}
}
time_t getFolderTreeContentsCheckSumRecursivelyLastGenerated(vector<string> paths, string pathSearchString, const string &filterFileExt) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"-------------- In [%s::%s Line: %d] Calculating CRC for [%s] -----------\n",__FILE__,__FUNCTION__,__LINE__,pathSearchString.c_str());
std::pair<string,string> cacheKeys = getFolderTreeContentsCheckSumCacheKey(paths, pathSearchString, filterFileExt);
//string cacheLookupId = cacheKeys.first;
//std::map<string,uint32> &crcTreeCache = CacheManager::getCachedItem< std::map<string,uint32> >(cacheLookupId);
string cacheKey = cacheKeys.second;
string crcCacheFile = getFormattedCRCCacheFileName(cacheKeys);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"-------------- In [%s::%s Line: %d] looking for cached CRC file [%s] for [%s] -----------\n",__FILE__,__FUNCTION__,__LINE__,crcCacheFile.c_str(),pathSearchString.c_str());
uint32 crcValue = 0;
pair<bool,time_t> crcResult = hasCachedFileCRCValue(crcCacheFile, crcValue);
if(crcResult.first == true) {
//struct tm *loctime = localtime (&crcResult.second);
struct tm loctime = threadsafe_localtime(crcResult.second);
char szBuf1[100]="";
strftime(szBuf1,100,"%Y-%m-%d %H:%M:%S",&loctime);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] scanning folders found CACHED FILE for cacheKey [%s] last updated [%s]\n",__FILE__,__FUNCTION__,__LINE__,cacheKey.c_str(),szBuf1);
//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\n-------------- In [%s::%s Line: %d] scanning folders found CACHED FILE for cacheKey [%s] last updated [%s]\n",__FILE__,__FUNCTION__,__LINE__,cacheKey.c_str(),szBuf1);
return crcResult.second;
}
else {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] scanning folders DID NOT FIND CACHED FILE checksum for cacheKey [%s]\n",__FILE__,__FUNCTION__,cacheKey.c_str());
//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\n-------------- In [%s::%s] scanning folders DID NOT FIND CACHED FILE checksum for cacheKey [%s]\n",__FILE__,__FUNCTION__,cacheKey.c_str());
}
return 0;
}
//finds all filenames like path and gets their checksum of all files combined
uint32 getFolderTreeContentsCheckSumRecursively(vector<string> paths, string pathSearchString, const string &filterFileExt, Checksum *recursiveChecksum, bool forceNoCache) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"-------------- In [%s::%s Line: %d] Calculating CRC for [%s] -----------\n",__FILE__,__FUNCTION__,__LINE__,pathSearchString.c_str());
std::pair<string,string> cacheKeys = getFolderTreeContentsCheckSumCacheKey(paths, pathSearchString, filterFileExt);
string cacheLookupId = cacheKeys.first;
std::map<string,uint32> &crcTreeCache = CacheManager::getCachedItem< std::map<string,uint32> >(cacheLookupId);
string cacheKey = cacheKeys.second;
if(forceNoCache == false && crcTreeCache.find(cacheKey) != crcTreeCache.end()) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] scanning folders found CACHED checksum = %d for cacheKey [%s]\n",__FILE__,__FUNCTION__,__LINE__,crcTreeCache[cacheKey],cacheKey.c_str());
//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\n-------------- In [%s::%s Line: %d] scanning folders found CACHED checksum = %d for cacheKey [%s]\n",__FILE__,__FUNCTION__,__LINE__,crcTreeCache[cacheKey],cacheKey.c_str());
return crcTreeCache[cacheKey];
}
string crcCacheFile = getFormattedCRCCacheFileName(cacheKeys);
//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Looking for CRC Cache file [%s]\n",crcCacheFile.c_str());
if(recursiveChecksum == NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"-------------- In [%s::%s Line: %d] looking for cached CRC file [%s] for [%s] forceNoCache = %d -----------\n",__FILE__,__FUNCTION__,__LINE__,crcCacheFile.c_str(),pathSearchString.c_str(),forceNoCache);
}
uint32 crcValue = 0;
if(forceNoCache == false && hasCachedFileCRCValue(crcCacheFile, crcValue).first == true) {
crcTreeCache[cacheKey] = crcValue;
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] scanning folders found CACHED FILE checksum = %d for cacheKey [%s] forceNoCache = %d\n",__FILE__,__FUNCTION__,__LINE__,crcTreeCache[cacheKey],cacheKey.c_str(),forceNoCache);
if(recursiveChecksum == NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"-------------- In [%s::%s Line: %d] scanning folders found CACHED FILE checksum = %d for cacheKey [%s] forceNoCache = %d\n",__FILE__,__FUNCTION__,__LINE__,crcTreeCache[cacheKey],cacheKey.c_str(),forceNoCache);
}
return crcTreeCache[cacheKey];
}
else {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] scanning folders DID NOT FIND CACHED FILE checksum for cacheKey [%s] forceNoCache = %d\n",__FILE__,__FUNCTION__,cacheKey.c_str(),forceNoCache);
if(recursiveChecksum == NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"-------------- In [%s::%s] scanning folders DID NOT FIND CACHED FILE checksum for cacheKey [%s] forceNoCache = %d\n",__FILE__,__FUNCTION__,cacheKey.c_str(),forceNoCache);
}
}
Checksum checksum = (recursiveChecksum == NULL ? Checksum() : *recursiveChecksum);
for(unsigned int idx = 0; idx < paths.size(); ++idx) {
string path = paths[idx] + pathSearchString;
getFolderTreeContentsCheckSumRecursively(path, filterFileExt, &checksum, forceNoCache);
}
if(recursiveChecksum != NULL) {
*recursiveChecksum = checksum;
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Final CRC file count: %d\n",__FILE__,__FUNCTION__,__LINE__,checksum.getFileCount());
uint32 result = checksum.getFinalFileListSum();
//if(forceNoCache == false) {
crcTreeCache[cacheKey] = result;
writeCachedFileCRCValue(crcCacheFile, crcTreeCache[cacheKey],getCRCCacheFileName(cacheKeys));
//}
return result;
}
std::pair<string,string> getFolderTreeContentsCheckSumCacheKey(const string &path, const string &filterFileExt) {
string cacheLookupId = CacheManager::getFolderTreeContentsCheckSumRecursivelyCacheLookupKey2;
string cacheKey = path + "_" + filterFileExt;
return make_pair(cacheLookupId,cacheKey);
}
void clearFolderTreeContentsCheckSum(const string &path, const string &filterFileExt) {
std::pair<string,string> cacheKeys = getFolderTreeContentsCheckSumCacheKey(path,filterFileExt);
string cacheLookupId = cacheKeys.first;
std::map<string,uint32> &crcTreeCache = CacheManager::getCachedItem< std::map<string,uint32> >(cacheLookupId);
string cacheKey = cacheKeys.second;
if(crcTreeCache.find(cacheKey) != crcTreeCache.end()) {
crcTreeCache.erase(cacheKey);
}
string crcCacheFile = getFormattedCRCCacheFileName(cacheKeys);
if(fileExists(crcCacheFile) == true) {
bool result = removeFile(crcCacheFile);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] fileitem [%s] result = %d\n",__FILE__,__FUNCTION__,__LINE__,crcCacheFile.c_str(),result);
}
}
//finds all filenames like path and gets their checksum of all files combined
uint32 getFolderTreeContentsCheckSumRecursively(const string &path, const string &filterFileExt, Checksum *recursiveChecksum, bool forceNoCache) {
std::pair<string,string> cacheKeys = getFolderTreeContentsCheckSumCacheKey(path, filterFileExt);
string cacheLookupId = cacheKeys.first;
std::map<string,uint32> &crcTreeCache = CacheManager::getCachedItem< std::map<string,uint32> >(cacheLookupId);
string cacheKey = cacheKeys.second;
if(forceNoCache == false && crcTreeCache.find(cacheKey) != crcTreeCache.end()) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] scanning [%s] found CACHED checksum = %d for cacheKey [%s]\n",__FILE__,__FUNCTION__,__LINE__,path.c_str(),crcTreeCache[cacheKey],cacheKey.c_str());
//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("\n-------------- In [%s::%s Line: %d] scanning [%s] found CACHED checksum = %d for cacheKey [%s]\n",__FILE__,__FUNCTION__,__LINE__,path.c_str(),crcTreeCache[cacheKey],cacheKey.c_str());
return crcTreeCache[cacheKey];
}
string crcCacheFile = getFormattedCRCCacheFileName(cacheKeys);
//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Looking for CRC Cache file [%s]\n",crcCacheFile.c_str());
if(recursiveChecksum == NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"-------------- In [%s::%s Line: %d] looking for cached CRC file [%s] for [%s] forceNoCache = %d -----------\n",__FILE__,__FUNCTION__,__LINE__,crcCacheFile.c_str(),path.c_str(),forceNoCache);
}
uint32 crcValue = 0;
if(forceNoCache == false && hasCachedFileCRCValue(crcCacheFile, crcValue).first == true) {
crcTreeCache[cacheKey] = crcValue;
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] scanning folders found CACHED FILE checksum = %d for cacheKey [%s] forceNoCache = %d\n",__FILE__,__FUNCTION__,__LINE__,crcTreeCache[cacheKey],cacheKey.c_str(),forceNoCache);
if(recursiveChecksum == NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"-------------- In [%s::%s Line: %d] scanning folders found CACHED FILE checksum = %d for cacheKey [%s] forceNoCache = %d\n",__FILE__,__FUNCTION__,__LINE__,crcTreeCache[cacheKey],cacheKey.c_str(),forceNoCache);
}
return crcTreeCache[cacheKey];
}
else {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] scanning folders DID NOT FIND CACHED FILE checksum for cacheKey [%s] forceNoCache = %d\n",__FILE__,__FUNCTION__,cacheKey.c_str(),forceNoCache);
if(recursiveChecksum == NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"-------------- In [%s::%s] scanning folders DID NOT FIND CACHED FILE checksum for cacheKey [%s] forceNoCache = %d\n",__FILE__,__FUNCTION__,cacheKey.c_str(),forceNoCache);
}
}
bool topLevelCaller = (recursiveChecksum == NULL);
Checksum checksum = (recursiveChecksum == NULL ? Checksum() : *recursiveChecksum);
std::string mypath = path;
// Stupid win32 is searching for all files without extension when *. is
// specified as wildcard
//
if((int)mypath.size() >= 2 && mypath.compare(max((int)0,(int)mypath.size() - 2), 2, "*.") == 0) {
mypath = mypath.substr(0, max((int)0,(int)mypath.size() - 2));
mypath += "*";
}
glob_t globbuf;
int res = glob(mypath.c_str(), 0, 0, &globbuf);
#if !defined(__APPLE__) && !defined(__FreeBSD__)
if(res < 0) {
std::stringstream msg;
msg << "#2 Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw megaglest_runtime_error(msg.str());
}
#endif
int fileLoopCount = 0;
int fileMatchCount = 0;
for(int i = 0; i < (int)globbuf.gl_pathc; ++i) {
const char* p = globbuf.gl_pathv[i];
//printf("Line: %d p [%s]\n",__LINE__,p);
if(isdir(p) == false) {
bool addFile = true;
if(EndsWith(p, ".") == true || EndsWith(p, "..") == true || EndsWith(p, ".git") == true) {
addFile = false;
}
else if(filterFileExt != "") {
addFile = EndsWith(p, filterFileExt);
}
if(addFile) {
checksum.addFile(p);
fileMatchCount++;
}
}
fileLoopCount++;
}
globfree(&globbuf);
// Look recursively for sub-folders
#if defined(__APPLE__) || defined(__FreeBSD__)
res = glob(mypath.c_str(), 0, 0, &globbuf);
#else
res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf);
#endif
#if !defined(__APPLE__) && !defined(__FreeBSD__)
if(res < 0) {
std::stringstream msg;
msg << "#3 Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw megaglest_runtime_error(msg.str());
}
#endif
for(int i = 0; i < (int)globbuf.gl_pathc; ++i) {
#if defined(__APPLE__) || defined(__FreeBSD__)
struct stat statStruct;
// only process if dir..
int actStat = lstat( globbuf.gl_pathv[i], &statStruct);
if( S_ISDIR(statStruct.st_mode) == 0)
continue;
#endif
const char *p = globbuf.gl_pathv[i];
//printf("Line: %d p [%s]\n",__LINE__,p);
string currentPath = p;
endPathWithSlash(currentPath);
getFolderTreeContentsCheckSumRecursively(currentPath + "*", filterFileExt, &checksum, forceNoCache);
}
globfree(&globbuf);
if(recursiveChecksum != NULL) {
*recursiveChecksum = checksum;
}
if(topLevelCaller == true) {
//printf("In [%s::%s Line: %d] Final CRC file count for [%s]: %d\n",__FILE__,__FUNCTION__,__LINE__,path.c_str(),checksum.getFileCount());
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] Final CRC file count for [%s]: %d\n",__FILE__,__FUNCTION__,__LINE__,path.c_str(),checksum.getFileCount());
uint32 result = checksum.getFinalFileListSum();
//if(forceNoCache == false) {
crcTreeCache[cacheKey] = result;
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] scanning [%s] ending checksum = %d for cacheKey [%s] fileMatchCount = %d, fileLoopCount = %d\n",__FILE__,__FUNCTION__,path.c_str(),crcTreeCache[cacheKey],cacheKey.c_str(),fileMatchCount,fileLoopCount);
writeCachedFileCRCValue(crcCacheFile, crcTreeCache[cacheKey],getCRCCacheFileName(cacheKeys));
//}
return result;
}
else {
return 0;
}
}
std::pair<string,string> getFolderTreeContentsCheckSumListCacheKey(vector<string> paths, string pathSearchString, const string &filterFileExt) {
string cacheLookupId = CacheManager::getFolderTreeContentsCheckSumListRecursivelyCacheLookupKey1;
string cacheKey = "";
for(unsigned int idx = 0; idx < paths.size(); ++idx) {
string path = paths[idx] + pathSearchString;
cacheKey += path + "_" + filterFileExt + "_";
}
return make_pair(cacheLookupId,cacheKey);
}
void clearFolderTreeContentsCheckSumList(vector<string> paths, string pathSearchString, const string &filterFileExt) {
std::pair<string,string> cacheKeys = getFolderTreeContentsCheckSumListCacheKey(paths, pathSearchString, filterFileExt);
string cacheLookupId = cacheKeys.first;
std::map<string,vector<std::pair<string,uint32> > > &crcTreeCache = CacheManager::getCachedItem< std::map<string,vector<std::pair<string,uint32> > > >(cacheLookupId);
string cacheKey = cacheKeys.second;
if(crcTreeCache.find(cacheKey) != crcTreeCache.end()) {
crcTreeCache.erase(cacheKey);
}
for(unsigned int idx = 0; idx < paths.size(); ++idx) {
string path = paths[idx];
clearFolderTreeContentsCheckSumList(path, filterFileExt);
}
string crcCacheFile = getFormattedCRCCacheFileName(cacheKeys);
if(fileExists(crcCacheFile) == true) {
bool result = removeFile(crcCacheFile);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] fileitem [%s] result = %d\n",__FILE__,__FUNCTION__,__LINE__,crcCacheFile.c_str(),result);
}
}
vector<std::pair<string,uint32> > getFolderTreeContentsCheckSumListRecursively(vector<string> paths, string pathSearchString, const string &filterFileExt, vector<std::pair<string,uint32> > *recursiveMap) {
std::pair<string,string> cacheKeys = getFolderTreeContentsCheckSumListCacheKey(paths, pathSearchString, filterFileExt);
string cacheLookupId = cacheKeys.first;
std::map<string,vector<std::pair<string,uint32> > > &crcTreeCache = CacheManager::getCachedItem< std::map<string,vector<std::pair<string,uint32> > > >(cacheLookupId);
string cacheKey = cacheKeys.second;
if(crcTreeCache.find(cacheKey) != crcTreeCache.end()) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] scanning folders found CACHED result for cacheKey [%s]\n",__FILE__,__FUNCTION__,__LINE__,cacheKey.c_str());
return crcTreeCache[cacheKey];
}
else {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] scanning folders, NO CACHE found result for cacheKey [%s]\n",__FILE__,__FUNCTION__,__LINE__,cacheKey.c_str());
}
bool topLevelCaller = (recursiveMap == NULL);
vector<std::pair<string,uint32> > checksumFiles = (recursiveMap == NULL ? vector<std::pair<string,uint32> >() : *recursiveMap);
for(unsigned int idx = 0; idx < paths.size(); ++idx) {
string path = paths[idx] + pathSearchString;
checksumFiles = getFolderTreeContentsCheckSumListRecursively(path, filterFileExt, &checksumFiles);
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] checksumFiles.size() = %d\n",__FILE__,__FUNCTION__,__LINE__,checksumFiles.size());
if(topLevelCaller == true) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] EXITING TOP LEVEL RECURSION, checksumFiles.size() = %d\n",__FILE__,__FUNCTION__,__LINE__,checksumFiles.size());
}
crcTreeCache[cacheKey] = checksumFiles;
return crcTreeCache[cacheKey];
}
//finds all filenames like path and gets the checksum of each file
vector<string> getFolderTreeContentsListRecursively(const string &path, const string &filterFileExt, bool includeFolders, vector<string> *recursiveMap) {
bool topLevelCaller = (recursiveMap == NULL);
vector<string> resultFiles = (recursiveMap == NULL ? vector<string>() : *recursiveMap);
std::string mypath = path;
/** Stupid win32 is searching for all files without extension when *. is
* specified as wildcard
*/
if((int)mypath.size() >= 2 && mypath.compare(max((int)0,(int)mypath.size() - 2), 2, "*.") == 0) {
mypath = mypath.substr(0, max((int)0,(int)mypath.size() - 2));
mypath += "*";
}
glob_t globbuf;
int globFlags = 0;
if(EndsWith(mypath,"{,.}*") == true) {
#ifndef WIN32
globFlags = GLOB_BRACE;
#else
// Windows glob source cannot handle GLOB_BRACE
// but that should be ok for win32 platform
replaceAll(mypath,"{,.}*","*");
#endif
}
int res = glob(mypath.c_str(), globFlags, 0, &globbuf);
#if !defined(__APPLE__) && !defined(__FreeBSD__)
if(res < 0) {
std::stringstream msg;
msg << "#4 Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw megaglest_runtime_error(msg.str());
}
#endif
for(int i = 0; i < (int)globbuf.gl_pathc; ++i) {
const char* p = globbuf.gl_pathv[i];
bool skipItem = (EndsWith(p, ".") == true || EndsWith(p, "..") == true);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"~~~~~~~~~~~ Glob file [%s] skipItem = %d\n",p,skipItem);
if(skipItem == false) {
if(isdir(p) == false) {
bool addFile = true;
if(filterFileExt != "") {
addFile = EndsWith(p, filterFileExt);
}
if(addFile) {
resultFiles.push_back(p);
}
}
else if(includeFolders == true) {
resultFiles.push_back(p);
}
}
}
globfree(&globbuf);
// Look recursively for sub-folders
#if defined(__APPLE__) || defined(__FreeBSD__)
res = glob(mypath.c_str(), 0, 0, &globbuf);
#else //APPLE doesn't have the GLOB_ONLYDIR definition..
globFlags |= GLOB_ONLYDIR;
res = glob(mypath.c_str(), globFlags, 0, &globbuf);
#endif
#if !defined(__APPLE__) && !defined(__FreeBSD__)
if(res < 0) {
std::stringstream msg;
msg << "#5 Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw megaglest_runtime_error(msg.str());
}
#endif
for(int i = 0; i < (int)globbuf.gl_pathc; ++i) {
#if defined(__APPLE__) || defined(__FreeBSD__)
struct stat statStruct;
// only get if dir..
int actStat = lstat( globbuf.gl_pathv[ i], &statStruct);
if( S_ISDIR(statStruct.st_mode) == 0)
continue;
#endif
const char* p = globbuf.gl_pathv[i];
bool skipItem = (EndsWith(p, ".") == true || EndsWith(p, "..") == true);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"~~~~~~~~~~~ Glob folder [%s] skipItem = %d\n",p,skipItem);
if(skipItem == false) {
if(includeFolders == true) {
resultFiles.push_back(p);
}
string currentPath = p;
endPathWithSlash(currentPath);
if(EndsWith(mypath,"{,.}*") == true) {
currentPath += "{,.}*";
}
else {
currentPath += "*";
}
resultFiles = getFolderTreeContentsListRecursively(currentPath, filterFileExt, includeFolders,&resultFiles);
}
}
globfree(&globbuf);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] scanning [%s]\n",__FILE__,__FUNCTION__,path.c_str());
if(topLevelCaller == true) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] EXITING TOP LEVEL RECURSION\n",__FILE__,__FUNCTION__,__LINE__);
}
return resultFiles;
}
std::pair<string,string> getFolderTreeContentsCheckSumListCacheKey(const string &path, const string &filterFileExt) {
string cacheLookupId = CacheManager::getFolderTreeContentsCheckSumListRecursivelyCacheLookupKey2;
string cacheKey = path + "_" + filterFileExt;
return make_pair(cacheLookupId,cacheKey);
}
void clearFolderTreeContentsCheckSumList(const string &path, const string &filterFileExt) {
std::pair<string,string> cacheKeys = getFolderTreeContentsCheckSumListCacheKey(path,filterFileExt);
string cacheLookupId = cacheKeys.first;
std::map<string,vector<std::pair<string,uint32> > > &crcTreeCache = CacheManager::getCachedItem< std::map<string,vector<std::pair<string,uint32> > > >(cacheLookupId);
string cacheKey = cacheKeys.second;
if(crcTreeCache.find(cacheKey) != crcTreeCache.end()) {
crcTreeCache.erase(cacheKey);
}
string crcCacheFile = getFormattedCRCCacheFileName(cacheKeys);
if(fileExists(crcCacheFile) == true) {
bool result = removeFile(crcCacheFile);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] fileitem [%s] result = %d\n",__FILE__,__FUNCTION__,__LINE__,crcCacheFile.c_str(),result);
}
}
//finds all filenames like path and gets the checksum of each file
vector<std::pair<string,uint32> > getFolderTreeContentsCheckSumListRecursively(const string &path, const string &filterFileExt, vector<std::pair<string,uint32> > *recursiveMap) {
std::pair<string,string> cacheKeys = getFolderTreeContentsCheckSumListCacheKey(path, filterFileExt);
string cacheLookupId = cacheKeys.first;
std::map<string,vector<std::pair<string,uint32> > > &crcTreeCache = CacheManager::getCachedItem< std::map<string,vector<std::pair<string,uint32> > > >(cacheLookupId);
string cacheKey = cacheKeys.second;
if(crcTreeCache.find(cacheKey) != crcTreeCache.end()) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] scanning [%s] FOUND CACHED result for cacheKey [%s]\n",__FILE__,__FUNCTION__,path.c_str(),cacheKey.c_str());
return crcTreeCache[cacheKey];
}
bool topLevelCaller = (recursiveMap == NULL);
vector<std::pair<string,uint32> > checksumFiles = (recursiveMap == NULL ? vector<std::pair<string,uint32> >() : *recursiveMap);
std::string mypath = path;
/** Stupid win32 is searching for all files without extension when *. is
* specified as wildcard
*/
if((int)mypath.size() >= 2 && mypath.compare(max((int)0,(int)mypath.size() - 2), 2, "*.") == 0) {
mypath = mypath.substr(0, max((int)0,(int)mypath.size() - 2));
mypath += "*";
}
glob_t globbuf;
int res = glob(mypath.c_str(), 0, 0, &globbuf);
#if !defined(__APPLE__) && !defined(__FreeBSD__)
if(res < 0) {
std::stringstream msg;
msg << "#6 Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw megaglest_runtime_error(msg.str());
}
#endif
for(int i = 0; i < (int)globbuf.gl_pathc; ++i) {
const char* p = globbuf.gl_pathv[i];
if(isdir(p) == false) {
bool addFile = true;
if(EndsWith(p, ".") == true || EndsWith(p, "..") == true || EndsWith(p, ".git") == true) {
addFile = false;
}
else if(filterFileExt != "") {
addFile = EndsWith(p, filterFileExt);
}
if(addFile) {
Checksum checksum;
checksum.addFile(p);
checksumFiles.push_back(std::pair<string,uint32>(p,checksum.getSum()));
}
}
}
globfree(&globbuf);
// Look recursively for sub-folders
#if defined(__APPLE__) || defined(__FreeBSD__)
res = glob(mypath.c_str(), 0, 0, &globbuf);
#else //APPLE doesn't have the GLOB_ONLYDIR definition..
res = glob(mypath.c_str(), GLOB_ONLYDIR, 0, &globbuf);
#endif
#if !defined(__APPLE__) && !defined(__FreeBSD__)
if(res < 0) {
std::stringstream msg;
msg << "#7 Couldn't scan directory '" << mypath << "': " << strerror(errno);
throw megaglest_runtime_error(msg.str());
}
#endif
for(int i = 0; i < (int)globbuf.gl_pathc; ++i) {
#if defined(__APPLE__) || defined(__FreeBSD__)
struct stat statStruct;
// only get if dir..
int actStat = lstat( globbuf.gl_pathv[ i], &statStruct);
if( S_ISDIR(statStruct.st_mode) == 0)
continue;
#endif
const char *p = globbuf.gl_pathv[i];
string currentPath = p;
endPathWithSlash(currentPath);
checksumFiles = getFolderTreeContentsCheckSumListRecursively(currentPath + "*", filterFileExt, &checksumFiles);
}
globfree(&globbuf);
crcTreeCache[cacheKey] = checksumFiles;
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] scanning [%s] cacheKey [%s] checksumFiles.size() = %d\n",__FILE__,__FUNCTION__,path.c_str(),cacheKey.c_str(),checksumFiles.size());
if(topLevelCaller == true) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] EXITING TOP LEVEL RECURSION, checksumFiles.size() = %d\n",__FILE__,__FUNCTION__,__LINE__,checksumFiles.size());
}
return crcTreeCache[cacheKey];
}
string extractFileFromDirectoryPath(string filename) {
size_t lastDirectory = filename.find_last_of("/\\");
if (lastDirectory == string::npos) {
return filename;
}
return filename.erase( 0, lastDirectory + 1);
}
string extractDirectoryPathFromFile(string filename) {
size_t lastDirectory = filename.find_last_of("/\\");
string path = "";
if (lastDirectory != string::npos) {
path = filename.substr( 0, lastDirectory + 1);
}
return path;
}
string extractLastDirectoryFromPath(string Path) {
string result = Path;
size_t lastDirectory = Path.find_last_of("/\\");
if (lastDirectory == string::npos) {
result = Path;
}
else {
if(Path.length() > lastDirectory + 1) {
result = Path.erase( 0, lastDirectory + 1);
}
else {
for(int i = (int)lastDirectory-1; i >= 0; --i) {
if((Path[i] == '/' || Path[i] == '\\') && i > 0) {
result = Path.erase( 0, i);
break;
}
}
}
}
return result;
}
string extractExtension(const string& filepath) {
size_t lastPoint = filepath.find_last_of('.');
size_t lastDirectory = filepath.find_last_of("/\\");
if (lastPoint == string::npos || (lastDirectory != string::npos && lastDirectory > lastPoint)) {
return "";
}
return filepath.substr(lastPoint+1);
}
void createDirectoryPaths(string Path) {
char DirName[256]="";
const char *path = Path.c_str();
char *dirName = DirName;
while(*path) {
//if (('\\' == *path) || ('/' == *path))
if ('/' == *path) {
if(isdir(DirName) == false) {
#ifdef WIN32
int result = _wmkdir(utf8_decode(DirName).c_str());
//int result = _mkdir(DirName);
#elif defined(__GNUC__)
int result = mkdir(DirName, S_IRWXU | S_IRWXO | S_IRWXG);
#else
#error "Your compiler needs to support mkdir!"
#endif
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] DirName [%s] result = %d, errno = %d\n",__FILE__,__FUNCTION__,__LINE__,DirName,result,errno);
}
}
*dirName++ = *path++;
*dirName = '\0';
}
#ifdef WIN32
//int result = _mkdir(DirName);
int result = _wmkdir(utf8_decode(DirName).c_str());
#elif defined(__GNUC__)
int result = mkdir(DirName, S_IRWXU | S_IRWXO | S_IRWXG);
#else
#error "Your compiler needs to support mkdir!"
#endif
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] DirName [%s] result = %d, errno = %d\n",__FILE__,__FUNCTION__,__LINE__,DirName,result,errno);
}
void getFullscreenVideoInfo(int &colorBits,int &screenWidth,int &screenHeight,bool isFullscreen) {
// TTSDL What does this method do ? I have no clue...
//
// // Get the current video hardware information
// //const SDL_VideoInfo* vidInfo = SDL_GetVideoInfo();
// //colorBits = vidInfo->vfmt->BitsPerPixel;
// //screenWidth = vidInfo->current_w;
// //screenHeight = vidInfo->current_h;
//
// if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
//
// /* Get available fullscreen/hardware modes */
//
// #if defined(WIN32) || defined(__APPLE__)
//
// int flags = 0;
//
// #else
//
// int flags = SDL_WINDOW_RESIZABLE;
//
// #endif
// if(isFullscreen) flags = SDL_WINDOW_FULLSCREEN;
// SDL_Rect**modes = SDL_ListModes(NULL, SDL_OPENGL|flags);
//
// /* Check if there are any modes available */
// if (modes == (SDL_Rect**)0) {
// if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] no hardware modes available.\n",__FILE__,__FUNCTION__,__LINE__);
//
// const SDL_VideoInfo* vidInfo = SDL_GetVideoInfo();
// colorBits = vidInfo->vfmt->BitsPerPixel;
// screenWidth = vidInfo->current_w;
// screenHeight = vidInfo->current_h;
//
// if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] using current resolution: %d x %d.\n",__FILE__,__FUNCTION__,__LINE__,screenWidth,screenHeight);
// }
// /* Check if our resolution is restricted */
// else if (modes == (SDL_Rect**)-1) {
// if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] all resolutions available.\n",__FILE__,__FUNCTION__,__LINE__);
//
// const SDL_VideoInfo* vidInfo = SDL_GetVideoInfo();
// colorBits = vidInfo->vfmt->BitsPerPixel;
// screenWidth = vidInfo->current_w;
// screenHeight = vidInfo->current_h;
//
// if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] using current resolution: %d x %d.\n",__FILE__,__FUNCTION__,__LINE__,screenWidth,screenHeight);
// }
// else{
// /* Print valid modes */
// if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] available Modes are:\n",__FILE__,__FUNCTION__,__LINE__);
//
// int bestW = -1;
// int bestH = -1;
// for(int i=0; modes[i]; ++i) {
// if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"%d x %d\n",modes[i]->w, modes[i]->h);
//
// if(bestW < modes[i]->w) {
// bestW = modes[i]->w;
// bestH = modes[i]->h;
// }
// }
//
// if(bestW > screenWidth) {
// screenWidth = bestW;
// screenHeight = bestH;
// }
//
// if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] using current resolution: %d x %d.\n",__FILE__,__FUNCTION__,__LINE__,screenWidth,screenHeight);
// }
}
void getFullscreenVideoModes(vector<ModeInfo> *modeinfos, bool isFullscreen) {
// Get the current video hardware information
//const SDL_VideoInfo* vidInfo = SDL_GetVideoInfo();
//colorBits = vidInfo->vfmt->BitsPerPixel;
//screenWidth = vidInfo->current_w;
//screenHeight = vidInfo->current_h;
if (SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled)
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
//SDL_PixelFormat format;
//SDL_Rect **modes;
//int loops(0);
//int bpp(0);
std::map<std::string,bool> uniqueResList;
///////////////////////////
vector<pair<int,int> > allResoltuions;
SDL_DisplayMode mode = {SDL_PIXELFORMAT_UNKNOWN, 0, 0, 0, 0};
int max=SDL_GetNumDisplayModes(0);
for (int i = 0; i < max; ++i) {
if(0==SDL_GetDisplayMode(0,i,&mode)) {
int bpp;
Uint32 Rmask;
Uint32 Gmask;
Uint32 Bmask;
Uint32 Amask;
SDL_PixelFormatEnumToMasks(mode.format,&bpp,&Rmask,&Gmask,&Bmask,&Amask);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"%d x %d\n",allResoltuions[i].first, allResoltuions[i].second,bpp);
string lookupKey = intToStr(mode.w) + "_" + intToStr(mode.h) + "_" + intToStr(bpp);
if(uniqueResList.find(lookupKey) == uniqueResList.end()) {
uniqueResList[lookupKey] = true;
modeinfos->push_back(ModeInfo(mode.w,mode.h,bpp));
}
}
}
//////////////////////////////////
std::sort(modeinfos->begin(),modeinfos->end());
}
void changeVideoModeFullScreen(bool value) {
Private::shouldBeFullscreen = value;
}
void restoreVideoMode(SDL_Window *sdlWindow,bool exitingApp) {
//SDL_Quit();
if(exitingApp == true && SDL_WasInit(SDL_INIT_VIDEO)) {
SDL_SetRelativeMouseMode(SDL_FALSE);
SDL_SetWindowBrightness(sdlWindow, 1.0f);
}
}
//int getScreenW() {
// return SDL_GetVideoSurface()->w; //SDL_GetWindowSurface()
//}
//
//int getScreenH() {
// return SDL_GetVideoSurface()->h;
//}
void sleep(int millis) {
SDL_Delay(millis);
}
bool isCursorShowing() {
int state = SDL_ShowCursor(SDL_QUERY);
return (state == SDL_ENABLE);
}
void showCursor(bool b) {
//printf("In showCursor, b: %d, isCursorShowing(): %d\n",b,isCursorShowing());
if(isCursorShowing() == b) {
return;
}
//printf("showCursor(bool b) b=%d\n",b);
SDL_ShowCursor(b == true ? SDL_ENABLE : SDL_DISABLE);
}
//bool isKeyDown(SDLKey key) {
// const Uint8* keystate = SDL_GetKeyboardState(0);
//
// if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] key = %d\n",__FILE__,__FUNCTION__,__LINE__,key);
//
// if(key >= 0) {
// if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] keystate[key] = %d\n",__FILE__,__FUNCTION__,__LINE__,keystate[key]);
//
// return (keystate[key] != 0);
// }
// if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] returning false\n",__FILE__,__FUNCTION__,__LINE__);
// return false;
//
//}
bool isKeyDown(int virtualKey) {
char key = static_cast<char> (virtualKey);
const Uint8* keystate = SDL_GetKeyboardState(0);
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] key = %d\n",__FILE__,__FUNCTION__,__LINE__,key);
if(key >= 0) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] keystate[key] = %d\n",__FILE__,__FUNCTION__,__LINE__,keystate[(unsigned char)key]);
return (keystate[(unsigned char)key] != 0);
}
switch(key) {
//SDLTT case vkAdd:
// return (keystate[SDL_SCANCODE_PLUS] != 0 || keystate[SDL_SCANCODE_KP_PLUS] != 0);
case vkSubtract:
return (keystate[SDL_SCANCODE_MINUS] != 0 || keystate[SDL_SCANCODE_KP_MINUS] != 0);
case vkAlt:
return (keystate[SDL_SCANCODE_LALT] != 0 || keystate[SDL_SCANCODE_RALT] != 0);
case vkControl:
return (keystate[SDL_SCANCODE_LCTRL] != 0 || keystate[SDL_SCANCODE_RCTRL] != 0);
case vkShift:
return (keystate[SDL_SCANCODE_LSHIFT] != 0 || keystate[SDL_SCANCODE_RSHIFT] != 0);
case vkEscape:
return (keystate[SDL_SCANCODE_ESCAPE] != 0);
case vkUp:
return (keystate[SDL_SCANCODE_UP] != 0);
case vkLeft:
return (keystate[SDL_SCANCODE_LEFT] != 0);
case vkRight:
return (keystate[SDL_SCANCODE_RIGHT] != 0);
case vkDown:
return (keystate[SDL_SCANCODE_DOWN] != 0);
case vkReturn:
return (keystate[SDL_SCANCODE_RETURN] != 0 || keystate[SDL_SCANCODE_KP_ENTER] != 0);
case vkBack:
return (keystate[SDL_SCANCODE_BACKSPACE] != 0);
case vkDelete:
return (keystate[SDL_SCANCODE_DELETE] != 0);
case vkPrint:
return (keystate[SDL_SCANCODE_PRINTSCREEN] != 0);
case vkPause:
return (keystate[SDL_SCANCODE_PAUSE] != 0);
default:
std::cerr << "isKeyDown called with unknown key.\n";
break;
}
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] returning false\n",__FILE__,__FUNCTION__,__LINE__);
return false;
}
string replaceAllHTMLEntities(string& context) {
replaceAll(context,"&quot;","\"");
replaceAll(context,"&amp;","&");
replaceAll(context,"&lt;","<");
replaceAll(context,"&gt;",">");
//replaceAll(context,"&OElig;","Œ");
replaceAll(context,"&OElig;","\xC5\x92\0");
//replaceAll(context,"&oelig;","œ");
replaceAll(context,"&oelig;","\xC5\x93\0");
//replaceAll(context,"&Scaron;","Š");
replaceAll(context,"&Scaron;","\xC5\xA0\0");
//replaceAll(context,"&scaron;","š");
replaceAll(context,"&scaron;","\xC5\xA1\0");
//replaceAll(context,"&Yuml;","Ÿ");
replaceAll(context,"&Yuml;","\xC5\xB8\0");
replaceAll(context,"&circ;","ˆ");
replaceAll(context,"&tilde;","˜");
replaceAll(context,"&ensp;"," ");
replaceAll(context,"&emsp;"," ");
replaceAll(context,"&thinsp;"," ");
replaceAll(context,"&ndash;","-");
replaceAll(context,"&mdash;","-");
//replaceAll(context,"&lsquo;","");
replaceAll(context,"&lsquo;","\xE2\x80\x98\0");
//replaceAll(context,"&rsquo;","");
replaceAll(context,"&rsquo;","\xE2\x80\x99\0");
//replaceAll(context,"&sbquo;","");
replaceAll(context,"&sbquo;","\xE2\x80\x9A\0");
//replaceAll(context,"&ldquo;","“");
replaceAll(context,"&ldquo;","\xE2\x80\x9C\0");
//replaceAll(context,"&rdquo;","”");
replaceAll(context,"&rdquo;","\xE2\x80\x9D\0");
//replaceAll(context,"&bdquo;","„");
replaceAll(context,"&bdquo;","\xE2\x80\x9E\0");
//replaceAll(context,"&dagger;","†");
replaceAll(context,"&dagger;","\xE2\x80\xA0\0");
//replaceAll(context,"&Dagger;","‡");
replaceAll(context,"&Dagger;","\xE2\x80\xA1\0");
//replaceAll(context,"&permil;","‰");
replaceAll(context,"&permil;","\xE2\x80\xB0\0");
//replaceAll(context,"&lsaquo;","");
replaceAll(context,"&lsaquo;","\xE2\x80\xB9\0");
//replaceAll(context,"&rsaquo;","");
replaceAll(context,"&rsaquo;","\xE2\x80\xBA\0");
//replaceAll(context,"&euro;","€");
replaceAll(context,"&euro;","\xE2\x82\xAC\0");
return context;
}
string replaceAll(string& context, const string& from, const string& to) {
size_t lookHere = 0;
size_t foundHere = 0;
if((foundHere = context.find(from, lookHere)) != string::npos) {
//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Replacing context [%s] from [%s] to [%s]\n",context.c_str(),from.c_str(),to.c_str());
while((foundHere = context.find(from, lookHere)) != string::npos) {
context.replace(foundHere, from.size(), to);
lookHere = foundHere + to.size();
}
//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("New context [%s]\n",context.c_str());
}
return context;
}
vector<char> replaceAllBetweenTokens(vector<char>& context,
const string &startToken, const string &endToken, const string &newText,
bool removeTokens) {
string newValue(context.begin(),context.end());
replaceAllBetweenTokens(newValue,startToken,endToken,newText,removeTokens);
context = vector<char>(newValue.begin(),newValue.end());
return context;
}
string replaceAllBetweenTokens(string& context, const string &startToken,
const string &endToken, const string &newText, bool removeTokens) {
size_t lookHere = 0;
size_t foundHere = 0;
if((foundHere = context.find(startToken, lookHere)) != string::npos) {
//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Replacing context [%s] from [%s] to [%s]\n",context.c_str(),from.c_str(),to.c_str());
while((foundHere = context.find(startToken, lookHere)) != string::npos) {
size_t foundHereEnd = context.find(endToken, foundHere+1);
if(foundHereEnd == string::npos) {
break;
}
if(removeTokens == true) {
foundHereEnd += endToken.size();
context.replace(foundHere, foundHereEnd-foundHere+1, newText);
lookHere = foundHere + newText.size();
}
else {
foundHere += startToken.size();
foundHereEnd -= 1;
context.replace(foundHere, foundHereEnd-foundHere+1, newText);
lookHere = foundHere + newText.size();
}
}
//if(SystemFlags::VERBOSE_MODE_ENABLED) printf("New context [%s]\n",context.c_str());
}
return context;
}
string getFullFileArchiveExtractCommand(string fileArchiveExtractCommand,
string fileArchiveExtractCommandParameters, string outputpath, string archivename) {
string parsedOutputpath = outputpath;
string parsedArchivename = archivename;
// This is required for execution on win32
#if defined(WIN32)
replaceAll(parsedOutputpath, "\\\\", "\\");
replaceAll(parsedOutputpath, "/", "\\");
replaceAll(parsedArchivename, "\\\\", "\\");
replaceAll(parsedArchivename, "/", "\\");
#endif
string result = fileArchiveExtractCommand;
result += " ";
string args = replaceAll(fileArchiveExtractCommandParameters, "{outputpath}", parsedOutputpath);
args = replaceAll(args, "{archivename}", parsedArchivename);
result += args;
return result;
}
string getFullFileArchiveCompressCommand(string fileArchiveCompressCommand,
string fileArchiveCompressCommandParameters,
string archivename, string archivefiles) {
string parsedArchivename = archivename;
string parsedArchivefiles = archivefiles;
// This is required for execution on win32
#if defined(WIN32)
replaceAll(parsedArchivename, "\\\\", "\\");
replaceAll(parsedArchivename, "/", "\\");
replaceAll(parsedArchivefiles, "\\\\", "\\");
replaceAll(parsedArchivefiles, "/", "\\");
#endif
string result = fileArchiveCompressCommand;
result += " ";
string args = replaceAll(fileArchiveCompressCommandParameters, "{archivename}", parsedArchivename);
args = replaceAll(args, "{archivefiles}", parsedArchivefiles);
result += args;
return result;
}
bool executeShellCommand(string cmd, int expectedResult, ShellCommandOutputCallbackInterface *cb) {
bool result = false;
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"About to run [%s]", cmd.c_str());
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("About to run [%s]", cmd.c_str());
#ifdef WIN32
FILE *file = _wpopen(utf8_decode(cmd).c_str(),L"r");
#else
FILE *file = popen(cmd.c_str(),"r");
#endif
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"file = [%p]", file);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("file = [%p]", file);
if(file != NULL) {
char szBuf[4096]="";
while(feof(file) == false) {
if(fgets( szBuf, 4095, file) != NULL) {
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"%s",szBuf);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("%s",szBuf);
if(cb != NULL) {
cb->ShellCommandOutput_CallbackEvent(cmd,szBuf,cb->getShellCommandOutput_UserData(cmd));
}
}
}
#ifdef WIN32
int cmdRet = _pclose(file);
#else
int cmdRet = pclose(file);
#endif
/* Close pipe and print return value. */
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"Process returned %d\n", cmdRet);
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("Process returned %d\n", cmdRet);
result = (expectedResult == IGNORE_CMD_RESULT_VALUE || expectedResult == cmdRet);
}
return result;
}
bool removeFile(string file) {
#ifdef WIN32
int result = _unlink(file.c_str());
#else
int result = unlink(file.c_str());
#endif
return (result == 0);
}
bool renameFile(string oldFile, string newFile) {
int result = rename(oldFile.c_str(),newFile.c_str());
return (result == 0);
}
off_t getFileSize(string filename) {
#ifdef WIN32
#if defined(__MINGW32__)
struct _stat stbuf;
#else
struct _stat64i32 stbuf;
#endif
if(_wstat(utf8_decode(filename).c_str(), &stbuf) != -1) {
#else
struct stat stbuf;
if(stat(filename.c_str(), &stbuf) != -1) {
#endif
return stbuf.st_size;
}
return 0;
}
string executable_path(string exeName, bool includeExeNameInPath) {
string value = "";
#ifdef _WIN32
char path[MAX_PATH]="";
if( GetModuleFileNameA(NULL,path,MAX_PATH) == 0 ) {
if(includeExeNameInPath == true) {
value = exeName;
}
else {
value = extractDirectoryPathFromFile(exeName);
}
}
else {
if(includeExeNameInPath == true) {
value = path;
}
else {
value = extractDirectoryPathFromFile(path);
}
}
#elif __APPLE__
char path[MAXPATHLEN+1]="";
uint32_t path_len = MAXPATHLEN;
if ( _NSGetExecutablePath(path, &path_len) ) {
if(includeExeNameInPath == true) {
value = exeName;
}
else {
value = extractDirectoryPathFromFile(exeName);
}
}
else {
if(includeExeNameInPath == true) {
value = path;
}
else {
value = extractDirectoryPathFromFile(path);
}
}
#else
char exe_link_path[200]="";
int length = readlink("/proc/self/exe", exe_link_path, sizeof(exe_link_path));
if(length < 0 || length >= 200 ) {
char *argv0_path = realpath(exeName.c_str(),NULL);
if(argv0_path != NULL) {
if(includeExeNameInPath == true) {
value = argv0_path;
}
else {
value = extractDirectoryPathFromFile(argv0_path);
}
free(argv0_path);
argv0_path = NULL;
}
else {
const char *shell_path = getenv("_");
if(shell_path != NULL) {
if(includeExeNameInPath == true) {
value = shell_path;
}
else {
value = extractDirectoryPathFromFile(shell_path);
}
}
else {
if(includeExeNameInPath == true) {
value = exeName;
}
else {
value = extractDirectoryPathFromFile(exeName);
}
}
}
}
else {
exe_link_path[length] = '\0';
if(includeExeNameInPath == true) {
value = exe_link_path;
}
else {
value = extractDirectoryPathFromFile(exe_link_path);
}
}
#endif
return value;
}
bool searchAndReplaceTextInFile(string fileName, string findText, string replaceText, bool simulateOnly) {
bool replacedText = false;
const int MAX_LEN_SINGLE_LINE = 4096;
char buffer[MAX_LEN_SINGLE_LINE+2];
char *buff_ptr, *find_ptr;
FILE *fp1, *fp2;
size_t find_len = findText.length();
string tempfileName = fileName + "_tmp";
#ifdef WIN32
fp1 = _wfopen(utf8_decode(fileName).c_str(), L"r");
fp2 = _wfopen(utf8_decode(tempfileName).c_str(), L"w");
#else
fp1 = fopen(fileName.c_str(),"r");
fp2 = fopen(tempfileName.c_str(),"w");
#endif
if(fp1 == NULL) {
if(fp2) fclose(fp2);
throw megaglest_runtime_error("cannot open input file [" + fileName + "]");
}
if(fp2 == NULL) {
if(fp1) fclose(fp1);
throw megaglest_runtime_error("cannot open output file [" + tempfileName + "]");
}
while(fgets(buffer,MAX_LEN_SINGLE_LINE + 2,fp1)) {
buff_ptr = buffer;
if(findText != "") {
while ((find_ptr = strstr(buff_ptr,findText.c_str()))) {
//printf("Replacing text [%s] with [%s] in file [%s]\n",findText.c_str(),replaceText.c_str(),fileName.c_str());
while(buff_ptr < find_ptr) {
fputc((int)*buff_ptr++,fp2);
}
fputs(replaceText.c_str(),fp2);
buff_ptr += find_len;
replacedText = true;
}
}
fputs(buff_ptr,fp2);
}
fclose(fp2);
fclose(fp1);
if(replacedText == true && simulateOnly == false) {
removeFile(fileName);
renameFile(tempfileName,fileName);
}
else {
removeFile(tempfileName);
}
//removeFile(tempfileName);
return replacedText;
}
void saveDataToFile(string filename, string data) {
//Open an input and output stream in binary mode
#if defined(WIN32) && !defined(__MINGW32__)
FILE *fp2 = _wfopen(utf8_decode(filename).c_str(), L"wb");
ofstream out(fp2);
#else
ofstream out(filename.c_str(),ios::binary);
#endif
if(out.is_open()) {
out<< data;
}
else if(out.is_open() == false) {
throw megaglest_runtime_error("cannot open input file [" + filename + "]");
}
//Close file
out.close();
#if defined(WIN32) && !defined(__MINGW32__)
if(fp2) {
fclose(fp2);
}
#endif
}
void copyFileTo(string fromFileName, string toFileName) {
//Open an input and output stream in binary mode
#if defined(WIN32) && !defined(__MINGW32__)
FILE *fp1 = _wfopen(utf8_decode(fromFileName).c_str(), L"rb");
ifstream in(fp1);
FILE *fp2 = _wfopen(utf8_decode(toFileName).c_str(), L"wb");
ofstream out(fp2);
#else
ifstream in(fromFileName.c_str(),ios::binary);
ofstream out(toFileName.c_str(),ios::binary);
#endif
if(in.is_open() && out.is_open()) {
while(in.eof() == false) {
out.put(in.get());
}
}
else if(in.is_open() == false) {
throw megaglest_runtime_error("cannot open input file [" + fromFileName + "]");
}
else if(out.is_open() == false) {
throw megaglest_runtime_error("cannot open input file [" + toFileName + "]");
}
//Close both files
in.close();
out.close();
#if defined(WIN32) && !defined(__MINGW32__)
if(fp1) {
fclose(fp1);
}
if(fp2) {
fclose(fp2);
}
#endif
}
bool valid_utf8_file(const char* file_name) {
#if defined(WIN32) && !defined(__MINGW32__)
wstring wstr = utf8_decode(file_name);
FILE *fp = _wfopen(wstr.c_str(), L"r");
ifstream ifs(fp);
#else
ifstream ifs(file_name);
#endif
if (!ifs) {
return false; // even better, throw here
}
istreambuf_iterator<char> it(ifs.rdbuf());
istreambuf_iterator<char> eos;
bool result = utf8::is_valid(it, eos);
ifs.close();
#if defined(WIN32) && !defined(__MINGW32__)
if(fp) {
fclose(fp);
}
#endif
return result;
}
string getFileTextContents(string path) {
#if defined(WIN32) && !defined(__MINGW32__)
FILE *fp = _wfopen(utf8_decode(path).c_str(), L"rb");
ifstream xmlFile(fp);
#else
ifstream xmlFile(path.c_str(),ios::binary);
#endif
if(xmlFile.is_open() == false) {
throw megaglest_runtime_error("Can not open file: [" + path + "]");
}
xmlFile.unsetf(ios::skipws);
// Determine stream size
xmlFile.seekg(0, ios::end);
streampos size = xmlFile.tellg();
xmlFile.seekg(0);
// Load data and add terminating 0
vector<char> buffer;
buffer.resize((unsigned int)size + 1);
xmlFile.read(&buffer.front(), static_cast<streamsize>(size));
buffer[(unsigned int)size] = 0;
return &buffer.front();
}
// =====================================
// ModeInfo
// =====================================
ModeInfo::ModeInfo(int w, int h, int d) {
width=w;
height=h;
depth=d;
}
string ModeInfo::getString() const{
return intToStr(width)+"x"+intToStr(height)+"-"+intToStr(depth);
}
void ValueCheckerVault::addItemToVault(const void *ptr,int value) {
#ifndef _DISABLE_MEMORY_VAULT_CHECKS
Checksum checksum;
vaultList[ptr] = checksum.addInt(value);
#endif
// if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s::%s Line: %d] add vault key [%p] value [%s] [%d]\n",__FILE__,__FUNCTION__,__LINE__,ptr,intToStr(checksum.getSum()).c_str(),value);
}
void ValueCheckerVault::checkItemInVault(const void *ptr,int value) const {
#ifndef _DISABLE_MEMORY_VAULT_CHECKS
map<const void *,uint32>::const_iterator iterFind = vaultList.find(ptr);
if(iterFind == vaultList.end()) {
// if(SystemFlags::VERBOSE_MODE_ENABLED) {
// printf("In [%s::%s Line: %d] check vault key [%p] value [%d]\n",__FILE__,__FUNCTION__,__LINE__,ptr,value);
// for(map<const void *,string>::const_iterator iterFind = vaultList.begin();
// iterFind != vaultList.end(); iterFind++) {
// printf("In [%s::%s Line: %d] LIST-- check vault key [%p] value [%s]\n",__FILE__,__FUNCTION__,__LINE__,iterFind->first,iterFind->second.c_str());
// }
// }
throw std::runtime_error("memory value has been unexpectedly modified (not found)!");
}
Checksum checksum;
if(iterFind->second != checksum.addInt(value)) {
// if(SystemFlags::VERBOSE_MODE_ENABLED) {
// printf("In [%s::%s Line: %d] check vault key [%p] value [%s] [%d]\n",__FILE__,__FUNCTION__,__LINE__,ptr,intToStr(checksum.getSum()).c_str(),value);
// for(map<const void *,string>::const_iterator iterFind = vaultList.begin();
// iterFind != vaultList.end(); iterFind++) {
// printf("In [%s::%s Line: %d] LIST-- check vault key [%p] value [%s]\n",__FILE__,__FUNCTION__,__LINE__,iterFind->first,iterFind->second.c_str());
// }
// }
throw std::runtime_error("memory value has been unexpectedly modified (changed)!");
}
#endif
}
string getUserHome() {
string home_folder;
home_folder = safeCharPtrCopy(getenv("HOME"),8095);
if(home_folder == "") {
#if _BSD_SOURCE || _SVID_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED
struct passwd *pw = getpwuid(getuid());
home_folder = safeCharPtrCopy(pw->pw_dir,8095);
#endif
}
return home_folder;
}
string safeCharPtrCopy(const char *ptr,int maxLength) {
string result = "";
if(ptr == NULL) {
return result;
}
if(maxLength <= 0) {
maxLength = 8096;
}
int ptrLength = (int)strlen(ptr);
if(ptrLength >= maxLength) {
char *pBuffer = new char[maxLength+1];
memset(pBuffer,0,maxLength+1);
#ifdef WIN32
memcpy(pBuffer,ptr,min((int)strlen(ptr),maxLength));
#else
memcpy(pBuffer,ptr,std::min((int)strlen(ptr),maxLength));
#endif
result = pBuffer;
delete [] pBuffer;
}
else {
result = ptr;
}
return result;
}
}}//end namespace