mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
VCMIDirs update #5
- Minor fixes - string based paths -> boost::filesystem::path paths (I hope it's final) - New user data path on windows - New moving dir method on windows.
This commit is contained in:
parent
2da6d9e7dd
commit
958839668c
13
Global.h
13
Global.h
@ -96,7 +96,11 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
|
||||
/* ---------------------------------------------------------------------------- */
|
||||
/* Commonly used C++, Boost headers */
|
||||
/* ---------------------------------------------------------------------------- */
|
||||
#ifndef VCMI_WINDOWS
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
#define NOMINMAX // Exclude min/max macros from <Windows.h>
|
||||
#endif
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
|
||||
#include <cstdio>
|
||||
@ -148,6 +152,7 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/functional/hash.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/locale/generator.hpp>
|
||||
#include <boost/logic/tribool.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/program_options.hpp>
|
||||
@ -158,10 +163,6 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/math/special_functions/round.hpp>
|
||||
|
||||
#ifdef VCMI_ANDROID
|
||||
#include <android/log.h>
|
||||
#endif
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
@ -196,7 +197,7 @@ typedef boost::lock_guard<boost::recursive_mutex> TLockGuardRec;
|
||||
/* Macros */
|
||||
/* ---------------------------------------------------------------------------- */
|
||||
// Import + Export macro declarations
|
||||
#ifdef _WIN32
|
||||
#ifdef VCMI_WINDOWS
|
||||
# ifdef __GNUC__
|
||||
# define DLL_EXPORT __attribute__((dllexport))
|
||||
# else
|
||||
@ -210,7 +211,7 @@ typedef boost::lock_guard<boost::recursive_mutex> TLockGuardRec;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef VCMI_WINDOWS
|
||||
# ifdef __GNUC__
|
||||
# define DLL_IMPORT __attribute__((dllimport))
|
||||
# else
|
||||
|
@ -1601,25 +1601,23 @@ int CPlayerInterface::getLastIndex( std::string namePrefix)
|
||||
path gamesDir = VCMIDirs::get().userSavePath();
|
||||
std::map<std::time_t, int> dates; //save number => datestamp
|
||||
|
||||
directory_iterator enddir;
|
||||
const directory_iterator enddir;
|
||||
if(!exists(gamesDir))
|
||||
create_directory(gamesDir);
|
||||
|
||||
for (directory_iterator dir(gamesDir); dir!=enddir; dir++)
|
||||
else
|
||||
for (directory_iterator dir(gamesDir); dir != enddir; ++dir)
|
||||
{
|
||||
if(is_regular(dir->status()))
|
||||
{
|
||||
std::string name = dir->path().leaf().string();
|
||||
std::string name = dir->path().filename().string();
|
||||
if(starts_with(name, namePrefix) && ends_with(name, ".vcgm1"))
|
||||
{
|
||||
char nr = name[namePrefix.size()];
|
||||
if(std::isdigit(nr))
|
||||
{
|
||||
dates[last_write_time(dir->path())] = boost::lexical_cast<int>(nr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!dates.empty())
|
||||
return (--dates.end())->second; //return latest file number
|
||||
|
@ -13,7 +13,7 @@ Editor::Editor(QWidget *parent)
|
||||
{
|
||||
// Setup default logging(enough for now)
|
||||
console = new CConsoleHandler;
|
||||
CBasicLogConfigurator logConfig(VCMIDirs::get().userCachePath() + "/VCMI_Editor_log.txt", console);
|
||||
CBasicLogConfigurator logConfig(VCMIDirs::get().userCachePath() / "VCMI_Editor_log.txt", console);
|
||||
logConfig.configureDefault();
|
||||
|
||||
preinitDLL(console);
|
||||
|
@ -9,3 +9,12 @@
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QFile>
|
||||
|
||||
inline QString pathToQString(const boost::filesystem::path & path)
|
||||
{
|
||||
#ifdef VCMI_WINDOWS
|
||||
return QString::fromStdWString(path.wstring());
|
||||
#else
|
||||
return QString::fromStdString(path.string());
|
||||
#endif
|
||||
}
|
@ -18,10 +18,10 @@ CLauncherDirs & CLauncherDirs::get()
|
||||
|
||||
QString CLauncherDirs::downloadsPath()
|
||||
{
|
||||
return QString::fromUtf8(VCMIDirs::get().userCachePath().c_str()) + "/downloads";
|
||||
return pathToQString(VCMIDirs::get().userCachePath() / "downloads");
|
||||
}
|
||||
|
||||
QString CLauncherDirs::modsPath()
|
||||
{
|
||||
return QString::fromUtf8(VCMIDirs::get().userDataPath().c_str()) + "/Mods";
|
||||
return pathToQString(VCMIDirs::get().userDataPath() / "Mods");
|
||||
}
|
||||
|
@ -13,15 +13,15 @@
|
||||
void MainWindow::load()
|
||||
{
|
||||
console = new CConsoleHandler;
|
||||
CBasicLogConfigurator logConfig(VCMIDirs::get().userCachePath() + "/VCMI_Launcher_log.txt", console);
|
||||
CBasicLogConfigurator logConfig(VCMIDirs::get().userCachePath() / "VCMI_Launcher_log.txt", console);
|
||||
logConfig.configureDefault();
|
||||
|
||||
CResourceHandler::initialize();
|
||||
CResourceHandler::load("config/filesystem.json");
|
||||
|
||||
for (auto & string : VCMIDirs::get().dataPaths())
|
||||
QDir::addSearchPath("icons", QString::fromUtf8(string.c_str()) + "/launcher/icons");
|
||||
QDir::addSearchPath("icons", QString::fromUtf8(VCMIDirs::get().userDataPath().c_str()) + "/launcher/icons");
|
||||
QDir::addSearchPath("icons", pathToQString(string / "launcher" / "icons"));
|
||||
QDir::addSearchPath("icons", pathToQString(VCMIDirs::get().userDataPath() / "launcher" / "icons"));
|
||||
|
||||
settings.init();
|
||||
}
|
||||
@ -46,7 +46,7 @@ MainWindow::~MainWindow()
|
||||
|
||||
void MainWindow::on_startGameButon_clicked()
|
||||
{
|
||||
startExecutable(QString::fromUtf8(VCMIDirs::get().clientPath().c_str()));
|
||||
startExecutable(pathToQString(VCMIDirs::get().clientPath()));
|
||||
}
|
||||
|
||||
void MainWindow::startExecutable(QString name)
|
||||
|
@ -39,7 +39,7 @@ CModManager::CModManager(CModList * modList):
|
||||
|
||||
QString CModManager::settingsPath()
|
||||
{
|
||||
return QString::fromUtf8(VCMIDirs::get().userConfigPath().c_str()) + "/modSettings.json";
|
||||
return pathToQString(VCMIDirs::get().userConfigPath() / "modSettings.json");
|
||||
}
|
||||
|
||||
void CModManager::loadModSettings()
|
||||
|
@ -46,9 +46,9 @@ void CSettingsView::loadSettings()
|
||||
for (auto entry : urls.Vector())
|
||||
ui->plainTextEditRepos->appendPlainText(QString::fromUtf8(entry.String().c_str()));
|
||||
|
||||
ui->lineEditUserDataDir->setText(QString::fromUtf8(VCMIDirs::get().userDataPath().c_str()));
|
||||
ui->lineEditGameDir->setText(QString::fromUtf8(M_DATA_DIR));
|
||||
ui->lineEditTempDir->setText(QString::fromUtf8(VCMIDirs::get().userCachePath().c_str()));
|
||||
ui->lineEditUserDataDir->setText(pathToQString(VCMIDirs::get().userDataPath()));
|
||||
ui->lineEditGameDir->setText(pathToQString(VCMIDirs::get().binaryPath()));
|
||||
ui->lineEditTempDir->setText(pathToQString(VCMIDirs::get().userCachePath()));
|
||||
|
||||
std::string encoding = settings["general"]["encoding"].String();
|
||||
size_t encodingIndex = boost::range::find(knownEncodingsList, encoding) - knownEncodingsList;
|
||||
|
@ -35,7 +35,7 @@ extern "C" DLL_EXPORT void BattleAI_GetNewBattleAI(shared_ptr<CBattleGameInterfa
|
||||
#endif
|
||||
|
||||
template<typename rett>
|
||||
shared_ptr<rett> createAny(std::string dllname, std::string methodName)
|
||||
shared_ptr<rett> createAny(const boost::filesystem::path& libpath, const std::string& methodName)
|
||||
{
|
||||
typedef void(*TGetAIFun)(shared_ptr<rett>&);
|
||||
typedef void(*TGetNameFun)(char*);
|
||||
@ -45,7 +45,13 @@ shared_ptr<rett> createAny(std::string dllname, std::string methodName)
|
||||
TGetAIFun getAI = nullptr;
|
||||
TGetNameFun getName = nullptr;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#ifndef VCMI_WINDOWS
|
||||
std::string dllname = libpath.string();
|
||||
// I don't know other platforms.
|
||||
// Somebody should remove it soon.
|
||||
#endif
|
||||
|
||||
#ifdef VCMI_ANDROID
|
||||
// this is awful but it seems using shared libraries on some devices is even worse
|
||||
if (dllname.find("libVCAI.so") != std::string::npos) {
|
||||
getName = (TGetNameFun)VCAI_GetAiName;
|
||||
@ -61,12 +67,12 @@ shared_ptr<rett> createAny(std::string dllname, std::string methodName)
|
||||
}
|
||||
#else
|
||||
|
||||
#ifdef _WIN32
|
||||
HINSTANCE dll = LoadLibraryA(dllname.c_str());
|
||||
#ifdef VCMI_WINDOWS
|
||||
HMODULE dll = LoadLibraryW(libpath.c_str());
|
||||
if (dll)
|
||||
{
|
||||
getName = (TGetNameFun)GetProcAddress(dll,"GetAiName");
|
||||
getAI = (TGetAIFun)GetProcAddress(dll,methodName.c_str());
|
||||
getName = (TGetNameFun)GetProcAddress(dll, "GetAiName");
|
||||
getAI = (TGetAIFun)GetProcAddress(dll, methodName.c_str());
|
||||
}
|
||||
#else
|
||||
void *dll = dlopen(dllname.c_str(), RTLD_LOCAL | RTLD_LAZY);
|
||||
@ -80,21 +86,20 @@ shared_ptr<rett> createAny(std::string dllname, std::string methodName)
|
||||
#endif
|
||||
if (!dll)
|
||||
{
|
||||
logGlobal->errorStream() << "Cannot open dynamic library ("<<dllname<<"). Throwing...";
|
||||
logGlobal->errorStream() << "Cannot open dynamic library ("<<libpath<<"). Throwing...";
|
||||
throw std::runtime_error("Cannot open dynamic library");
|
||||
}
|
||||
else if(!getName || !getAI)
|
||||
{
|
||||
logGlobal->errorStream() << dllname << " does not export method " << methodName;
|
||||
#ifdef _WIN32
|
||||
logGlobal->errorStream() << libpath << " does not export method " << methodName;
|
||||
#ifdef VCMI_WINDOWS
|
||||
FreeLibrary(dll);
|
||||
#else
|
||||
dlclose(dll);
|
||||
#endif
|
||||
throw std::runtime_error("Cannot find method " + methodName);
|
||||
}
|
||||
|
||||
#endif // __ANDROID__
|
||||
#endif // VCMI_ANDROID
|
||||
|
||||
getName(temp);
|
||||
logGlobal->infoStream() << "Loaded " << temp;
|
||||
@ -113,9 +118,8 @@ shared_ptr<rett> createAnyAI(std::string dllname, std::string methodName)
|
||||
logGlobal->infoStream() << "Opening " << dllname;
|
||||
const boost::filesystem::path filePath =
|
||||
VCMIDirs::get().libraryPath() / "AI" / VCMIDirs::get().libraryName(dllname);
|
||||
// TODO: createAny Should take boost::filesystem::path in argument.
|
||||
auto ret = createAny<rett>(filePath.string(), methodName);
|
||||
ret->dllName = dllname;
|
||||
auto ret = createAny<rett>(filePath, methodName);
|
||||
ret->dllName = std::move(dllname);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
169
lib/VCMIDirs.cpp
169
lib/VCMIDirs.cpp
@ -30,6 +30,75 @@ void IVCMIDirs::init()
|
||||
#include <Shlobj.h>
|
||||
#include <Shellapi.h>
|
||||
|
||||
// Generates script file named _temp.bat in 'to' directory and runs it
|
||||
// Script will:
|
||||
// - Wait util 'exeName' ends.
|
||||
// - Copy all files from 'from' to 'to'
|
||||
// - Ask user to replace files existed in 'to'.
|
||||
// - Run 'exeName'
|
||||
// - Delete itself.
|
||||
bool StartBatchCopyDataProgram(
|
||||
const bfs::path& from, const bfs::path& to, const bfs::path& exeName,
|
||||
const bfs::path& currentPath = bfs::current_path())
|
||||
{
|
||||
static const char base[] =
|
||||
"@echo off" "\n"
|
||||
"echo Preparing to move VCMI data system." "\n"
|
||||
|
||||
":CLIENT_RUNNING_LOOP" "\n"
|
||||
"TASKLIST | FIND /I %1% > nul" "\n"
|
||||
"IF ERRORLEVEL 1 (" "\n"
|
||||
"GOTO CLIENT_NOT_RUNNING" "\n"
|
||||
") ELSE (" "\n"
|
||||
"echo %1% is still running..." "\n"
|
||||
"echo Waiting until process ends..." "\n"
|
||||
"ping 1.1.1.1 -n 1 -w 3000 > nul" "\n" // Sleep ~3 seconds. I love Windows :)
|
||||
"goto :CLIENT_RUNNING_LOOP" "\n"
|
||||
")" "\n"
|
||||
|
||||
":CLIENT_NOT_RUNNING" "\n"
|
||||
"echo %1% turned off..." "\n"
|
||||
"echo Attempt to move datas." "\n"
|
||||
"echo From: %2%" "\n"
|
||||
"echo To: %4%" "\n"
|
||||
"echo Please resolve any conflicts..." "\n"
|
||||
"move /-Y %3% %4%" "\n" // Move all files from %3% to %4%.
|
||||
// /-Y ask what to do when file exists in %4%
|
||||
":REMOVE_OLD_DIR" "\n"
|
||||
"rd %2% || rem" "\n" // Remove empty directory. Sets error flag if fail.
|
||||
"IF ERRORLEVEL 145 (" "\n" // Directory not empty
|
||||
"echo Directory %2% is not empty." "\n"
|
||||
"echo Please move rest of files manually now." "\n"
|
||||
"pause" "\n" // Press any key to continue...
|
||||
"goto REMOVE_OLD_DIR" "\n"
|
||||
")" "\n"
|
||||
"echo Game data updated succefully." "\n"
|
||||
"echo Please update your shortcuts." "\n"
|
||||
"echo Press any key to start a game . . ." "\n"
|
||||
"pause > nul" "\n"
|
||||
"%5%" "\n"
|
||||
"del \"%%~f0\"&exit" "\n" // Script deletes itself
|
||||
;
|
||||
|
||||
const auto startGameString =
|
||||
bfs::equivalent(currentPath, from) ?
|
||||
(boost::format("start \"\" %1%") % (to / exeName)) : // Start game in new path.
|
||||
(boost::format("start \"\" /D %1% %2%") % currentPath % (to / exeName)); // Start game in 'currentPath"
|
||||
|
||||
const bfs::path bathFilename = to / "_temp.bat";
|
||||
bfs::ofstream bathFile(bathFilename, bfs::ofstream::trunc | bfs::ofstream::out);
|
||||
if (!bathFile.is_open())
|
||||
return false;
|
||||
bathFile << (boost::format(base) % exeName % from % (from / "*.*") % to % startGameString.str()).str();
|
||||
bathFile.close();
|
||||
|
||||
std::system(("start \"Updating VCMI datas\" /D \"" + to.string() + "\" \"" + bathFilename.string() + '\"').c_str());
|
||||
// start won't block std::system
|
||||
// /D start bat in other directory insteand of current directory.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class VCMIDirsWIN32 : public IVCMIDirs
|
||||
{
|
||||
public:
|
||||
@ -50,6 +119,9 @@ class VCMIDirsWIN32 : public IVCMIDirs
|
||||
std::string genHelpString() const override;
|
||||
|
||||
void init() override;
|
||||
protected:
|
||||
boost::filesystem::path oldUserDataPath() const;
|
||||
boost::filesystem::path oldUserSavePath() const;
|
||||
};
|
||||
|
||||
void VCMIDirsWIN32::init()
|
||||
@ -57,15 +129,21 @@ void VCMIDirsWIN32::init()
|
||||
// Call base (init dirs)
|
||||
IVCMIDirs::init();
|
||||
|
||||
auto moveDirIfExists = [](const bfs::path& from, const bfs::path& to)
|
||||
// Moves one directory (from) contents to another directory (to)
|
||||
// Shows user the "moving file dialog" and ask to resolve conflits.
|
||||
// If necessary updates current directory.
|
||||
auto moveDirIfExists = [](const bfs::path& from, const bfs::path& to) -> bool
|
||||
{
|
||||
if (!bfs::is_directory(from))
|
||||
return; // Nothing to do here. Flies away.
|
||||
return true; // Nothing to do here. Flies away.
|
||||
|
||||
if (bfs::is_empty(from))
|
||||
{
|
||||
if (bfs::current_path() == from)
|
||||
bfs::current_path(to);
|
||||
|
||||
bfs::remove(from);
|
||||
return; // Nothing to do here. Flies away.
|
||||
return true; // Nothing to do here. Flies away.
|
||||
}
|
||||
|
||||
if (!bfs::is_directory(to))
|
||||
@ -103,23 +181,87 @@ void VCMIDirsWIN32::init()
|
||||
fileOp.lpszProgressTitle = nullptr;
|
||||
|
||||
const int errorCode = SHFileOperationW(&fileOp);
|
||||
if (errorCode != 0); // TODO: Log error. User should try to move files.
|
||||
else if (fileOp.fAnyOperationsAborted); // TODO: Log warn. User aborted operation. User should move files.
|
||||
else if (!bfs::is_empty(from)); // TODO: Log warn. Some files not moved. User should try to move files.
|
||||
else // TODO: Log fact that we moved files succefully.
|
||||
if (errorCode != 0) // TODO: Log error. User should try to move files.
|
||||
return false;
|
||||
else if (fileOp.fAnyOperationsAborted) // TODO: Log warn. User aborted operation. User should move files.
|
||||
return false;
|
||||
else if (!bfs::is_empty(from)) // TODO: Log warn. Some files not moved. User should try to move files.
|
||||
return false;
|
||||
|
||||
if (bfs::current_path() == from)
|
||||
bfs::current_path(to);
|
||||
|
||||
// TODO: Log fact that we moved files succefully.
|
||||
bfs::remove(from);
|
||||
return true;
|
||||
};
|
||||
|
||||
moveDirIfExists(userDataPath() / "Games", userSavePath());
|
||||
// Retrieves the fully qualified path for the file that contains the specified module.
|
||||
// The module must have been loaded by the current process.
|
||||
// If this parameter is nullptr, retrieves the path of the executable file of the current process.
|
||||
auto getModulePath = [](HMODULE hModule) -> bfs::path
|
||||
{
|
||||
wchar_t exePathW[MAX_PATH];
|
||||
DWORD nSize = GetModuleFileNameW(hModule, exePathW, MAX_PATH);
|
||||
DWORD error = GetLastError();
|
||||
// WARN: Windows XP don't set ERROR_INSUFFICIENT_BUFFER error.
|
||||
if (nSize != 0 && error != ERROR_INSUFFICIENT_BUFFER)
|
||||
return bfs::path(std::wstring(exePathW, nSize));
|
||||
// TODO: Error handling
|
||||
return bfs::path();
|
||||
};
|
||||
|
||||
// Moves one directory contents to another directory
|
||||
// Shows user the "moving file dialog" and ask to resolve conflicts.
|
||||
// It takes into account that 'from' path can contain current executable.
|
||||
// If necessary closes program and starts update script.
|
||||
auto advancedMoveDirIfExists = [getModulePath, moveDirIfExists](const bfs::path& from, const bfs::path& to) -> bool
|
||||
{
|
||||
const bfs::path executablePath = getModulePath(nullptr);
|
||||
|
||||
// VCMI cann't determine executable path.
|
||||
// Use standard way to move directory and exit function.
|
||||
if (executablePath.empty())
|
||||
return moveDirIfExists(from, to);
|
||||
|
||||
const bfs::path executableName = executablePath.filename();
|
||||
|
||||
// Current executabl isn't in 'from' path.
|
||||
// Use standard way to move directory and exit function.
|
||||
if (!bfs::equivalent(executablePath, from / executableName))
|
||||
return moveDirIfExists(from, to);
|
||||
|
||||
// Try standard way to move directory.
|
||||
// I don't know how other systems, but Windows 8.1 allow to move running executable.
|
||||
if (moveDirIfExists(from, to))
|
||||
return true;
|
||||
|
||||
// Start copying script and exit program.
|
||||
if (StartBatchCopyDataProgram(from, to, executableName))
|
||||
exit(ERROR_SUCCESS);
|
||||
|
||||
// Everything failed :C
|
||||
return false;
|
||||
};
|
||||
|
||||
moveDirIfExists(oldUserSavePath(), userSavePath());
|
||||
advancedMoveDirIfExists(oldUserDataPath(), userDataPath());
|
||||
}
|
||||
|
||||
bfs::path VCMIDirsWIN32::userDataPath() const
|
||||
{
|
||||
wchar_t profileDir[MAX_PATH];
|
||||
|
||||
// The user's profile folder. A typical path is C:\Users\username.
|
||||
// FIXME: Applications should not create files or folders at this level;
|
||||
// they should put their data under the locations referred to by CSIDL_APPDATA or CSIDL_LOCAL_APPDATA.
|
||||
if (SHGetSpecialFolderPathW(nullptr, profileDir, CSIDL_MYDOCUMENTS, FALSE) != FALSE)
|
||||
return bfs::path(profileDir) / "My Games\\vcmi";
|
||||
|
||||
return ".";
|
||||
}
|
||||
|
||||
bfs::path VCMIDirsWIN32::oldUserDataPath() const
|
||||
{
|
||||
wchar_t profileDir[MAX_PATH];
|
||||
|
||||
if (SHGetSpecialFolderPathW(nullptr, profileDir, CSIDL_PROFILE, FALSE) == FALSE) // WinAPI way failed
|
||||
{
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1700
|
||||
@ -145,6 +287,8 @@ bfs::path VCMIDirsWIN32::userDataPath() const
|
||||
|
||||
//return dataPaths()[0] ???;
|
||||
}
|
||||
bfs::path VCMIDirsWIN32::oldUserSavePath() const { return userDataPath() / "Games"; }
|
||||
|
||||
bfs::path VCMIDirsWIN32::userCachePath() const { return userDataPath(); }
|
||||
bfs::path VCMIDirsWIN32::userConfigPath() const { return userDataPath() / "config"; }
|
||||
|
||||
@ -421,6 +565,9 @@ namespace VCMIDirs
|
||||
static bool initialized = false;
|
||||
if (!initialized)
|
||||
{
|
||||
std::locale::global(boost::locale::generator().generate("en_US.UTF-8"));
|
||||
boost::filesystem::path::imbue(std::locale());
|
||||
|
||||
singleton.init();
|
||||
initialized = true;
|
||||
}
|
||||
|
@ -9,15 +9,6 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// STL C++
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Boost
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
// TODO: File should be renamed to IVCMIDirs.h
|
||||
|
||||
class DLL_LINKAGE IVCMIDirs
|
||||
{
|
||||
public:
|
||||
|
@ -13,9 +13,9 @@ ArchiveEntry::ArchiveEntry()
|
||||
|
||||
}
|
||||
|
||||
CArchiveLoader::CArchiveLoader(const std::string &mountPoint, const std::string & archive):
|
||||
archive(archive),
|
||||
mountPoint(mountPoint)
|
||||
CArchiveLoader::CArchiveLoader(std::string _mountPoint, boost::filesystem::path _archive) :
|
||||
archive(std::move(_archive)),
|
||||
mountPoint(std::move(_mountPoint))
|
||||
{
|
||||
// Open archive file(.snd, .vid, .lod)
|
||||
CFileInputStream fileStream(archive);
|
||||
@ -25,28 +25,19 @@ CArchiveLoader::CArchiveLoader(const std::string &mountPoint, const std::string
|
||||
return;
|
||||
|
||||
// Retrieve file extension of archive in uppercase
|
||||
CFileInfo fileInfo(archive);
|
||||
std::string ext = fileInfo.getExtension();
|
||||
boost::to_upper(ext);
|
||||
const std::string ext = boost::to_upper_copy(archive.extension().string());
|
||||
|
||||
// Init the specific lod container format
|
||||
if(ext == ".LOD" || ext == ".PAC")
|
||||
{
|
||||
initLODArchive(mountPoint, fileStream);
|
||||
}
|
||||
else if(ext == ".VID")
|
||||
{
|
||||
initVIDArchive(mountPoint, fileStream);
|
||||
}
|
||||
else if(ext == ".SND")
|
||||
{
|
||||
initSNDArchive(mountPoint, fileStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("LOD archive format unknown. Cannot deal with " + archive);
|
||||
}
|
||||
logGlobal->traceStream() << ext << "Archive loaded, " << entries.size() << " files found";
|
||||
throw std::runtime_error("LOD archive format unknown. Cannot deal with " + archive.string());
|
||||
|
||||
logGlobal->traceStream() << ext << "Archive \""<<archive.filename()<<"\" loaded (" << entries.size() << " files found).";
|
||||
}
|
||||
|
||||
void CArchiveLoader::initLODArchive(const std::string &mountPoint, CFileInputStream & fileStream)
|
||||
@ -61,7 +52,7 @@ void CArchiveLoader::initLODArchive(const std::string &mountPoint, CFileInputStr
|
||||
fileStream.seek(0x5c);
|
||||
|
||||
// Insert entries to list
|
||||
for(ui32 i = 0; i < totalFiles; i++)
|
||||
for(ui32 i = 0; i < totalFiles; ++i)
|
||||
{
|
||||
char filename[16];
|
||||
reader.read(reinterpret_cast<ui8*>(filename), 16);
|
||||
@ -90,7 +81,7 @@ void CArchiveLoader::initVIDArchive(const std::string &mountPoint, CFileInputStr
|
||||
std::set<int> offsets;
|
||||
|
||||
// Insert entries to list
|
||||
for(ui32 i = 0; i < totalFiles; i++)
|
||||
for(ui32 i = 0; i < totalFiles; ++i)
|
||||
{
|
||||
char filename[40];
|
||||
reader.read(reinterpret_cast<ui8*>(filename), 40);
|
||||
@ -122,7 +113,7 @@ void CArchiveLoader::initSNDArchive(const std::string &mountPoint, CFileInputStr
|
||||
ui32 totalFiles = reader.readUInt32();
|
||||
|
||||
// Insert entries to list
|
||||
for(ui32 i = 0; i < totalFiles; i++)
|
||||
for(ui32 i = 0; i < totalFiles; ++i)
|
||||
{
|
||||
char filename[40];
|
||||
reader.read(reinterpret_cast<ui8*>(filename), 40);
|
||||
|
@ -55,7 +55,7 @@ public:
|
||||
*
|
||||
* @throws std::runtime_error if the archive wasn't found or if the archive isn't supported
|
||||
*/
|
||||
explicit CArchiveLoader(const std::string & mountPoint, const std::string & archive);
|
||||
CArchiveLoader(std::string mountPoint, boost::filesystem::path archive);
|
||||
|
||||
/// Interface implementation
|
||||
/// @see ISimpleResourceLoader
|
||||
@ -87,7 +87,7 @@ private:
|
||||
void initSNDArchive(const std::string &mountPoint, CFileInputStream & fileStream);
|
||||
|
||||
/** The file path to the archive which is scanned and indexed. */
|
||||
std::string archive;
|
||||
boost::filesystem::path archive;
|
||||
|
||||
std::string mountPoint;
|
||||
|
||||
|
@ -41,17 +41,17 @@ std::string CFileInfo::getPath() const
|
||||
std::string CFileInfo::getExtension() const
|
||||
{
|
||||
// Get position of file extension dot
|
||||
size_t dotPos = name.find_last_of("/.");
|
||||
size_t dotPos = name.find_last_of('.');
|
||||
|
||||
if(dotPos != std::string::npos && name[dotPos] == '.')
|
||||
if(dotPos != std::string::npos)
|
||||
return name.substr(dotPos);
|
||||
else
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string CFileInfo::getFilename() const
|
||||
{
|
||||
size_t found = name.find_last_of("/\\");
|
||||
const size_t found = name.find_last_of("/\\");
|
||||
return name.substr(found + 1);
|
||||
}
|
||||
|
||||
@ -60,9 +60,9 @@ std::string CFileInfo::getStem() const
|
||||
std::string rslt = name;
|
||||
|
||||
// Remove file extension
|
||||
size_t dotPos = name.find_last_of("/.");
|
||||
const size_t dotPos = name.find_last_of('.');
|
||||
|
||||
if(dotPos != std::string::npos && name[dotPos] == '.')
|
||||
if(dotPos != std::string::npos)
|
||||
rslt.erase(dotPos);
|
||||
|
||||
return rslt;
|
||||
@ -70,18 +70,19 @@ std::string CFileInfo::getStem() const
|
||||
|
||||
std::string CFileInfo::getBaseName() const
|
||||
{
|
||||
size_t begin = name.find_last_of("/");
|
||||
size_t end = name.find_last_of("/.");
|
||||
|
||||
if(end != std::string::npos && name[end] == '/')
|
||||
end = std::string::npos;
|
||||
size_t begin = name.find_last_of("/\\");
|
||||
size_t end = name.find_last_of(".");
|
||||
|
||||
if(begin == std::string::npos)
|
||||
begin = 0;
|
||||
else
|
||||
begin++;
|
||||
++begin;
|
||||
|
||||
return name.substr(begin, end - begin);
|
||||
if (end < begin)
|
||||
end = std::string::npos;
|
||||
|
||||
size_t len = (end == std::string::npos ? std::string::npos : end - begin);
|
||||
return name.substr(begin, len);
|
||||
}
|
||||
|
||||
EResType::Type CFileInfo::getType() const
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
#include "CFileInfo.h"
|
||||
|
||||
CFileInputStream::CFileInputStream(const std::string & file, si64 start, si64 size)
|
||||
CFileInputStream::CFileInputStream(const boost::filesystem::path & file, si64 start, si64 size)
|
||||
{
|
||||
open(file, start, size);
|
||||
}
|
||||
@ -18,14 +18,12 @@ CFileInputStream::~CFileInputStream()
|
||||
fileStream.close();
|
||||
}
|
||||
|
||||
void CFileInputStream::open(const std::string & file, si64 start, si64 size)
|
||||
void CFileInputStream::open(const boost::filesystem::path & file, si64 start, si64 size)
|
||||
{
|
||||
fileStream.open(file.c_str(), std::ios::in | std::ios::binary);
|
||||
fileStream.open(file, std::ios::in | std::ios::binary);
|
||||
|
||||
if (fileStream.fail())
|
||||
{
|
||||
throw std::runtime_error("File " + file + " isn't available.");
|
||||
}
|
||||
throw std::runtime_error("File " + file.string() + " isn't available.");
|
||||
|
||||
dataStart = start;
|
||||
dataSize = size;
|
||||
|
@ -25,7 +25,7 @@ public:
|
||||
*
|
||||
* @see CFileInputStream::open
|
||||
*/
|
||||
CFileInputStream(const std::string & file, si64 start=0, si64 size=0);
|
||||
CFileInputStream(const boost::filesystem::path & file, si64 start = 0, si64 size = 0);
|
||||
|
||||
/**
|
||||
* C-tor. Opens the specified file.
|
||||
@ -88,11 +88,11 @@ private:
|
||||
*
|
||||
* @throws std::runtime_error if file wasn't found
|
||||
*/
|
||||
void open(const std::string & file, si64 start, si64 size);
|
||||
void open(const boost::filesystem::path & file, si64 start, si64 size);
|
||||
|
||||
si64 dataStart;
|
||||
si64 dataSize;
|
||||
|
||||
/** Native c++ input file stream object. */
|
||||
std::ifstream fileStream;
|
||||
boost::filesystem::ifstream fileStream;
|
||||
};
|
||||
|
@ -4,9 +4,11 @@
|
||||
#include "CFileInfo.h"
|
||||
#include "CFileInputStream.h"
|
||||
|
||||
CFilesystemLoader::CFilesystemLoader(const std::string &mountPoint, const std::string & baseDirectory, size_t depth, bool initial):
|
||||
baseDirectory(baseDirectory),
|
||||
mountPoint(mountPoint),
|
||||
namespace bfs = boost::filesystem;
|
||||
|
||||
CFilesystemLoader::CFilesystemLoader(std::string _mountPoint, bfs::path baseDirectory, size_t depth, bool initial):
|
||||
baseDirectory(std::move(baseDirectory)),
|
||||
mountPoint(std::move(_mountPoint)),
|
||||
fileList(listFiles(mountPoint, depth, initial))
|
||||
{
|
||||
logGlobal->traceStream() << "Filesystem loaded, " << fileList.size() << " files found";
|
||||
@ -16,7 +18,7 @@ std::unique_ptr<CInputStream> CFilesystemLoader::load(const ResourceID & resourc
|
||||
{
|
||||
assert(fileList.count(resourceName));
|
||||
|
||||
std::unique_ptr<CInputStream> stream(new CFileInputStream(baseDirectory + '/' + fileList.at(resourceName)));
|
||||
std::unique_ptr<CInputStream> stream(new CFileInputStream(baseDirectory / fileList.at(resourceName)));
|
||||
return stream;
|
||||
}
|
||||
|
||||
@ -34,7 +36,7 @@ boost::optional<std::string> CFilesystemLoader::getResourceName(const ResourceID
|
||||
{
|
||||
assert(existsResource(resourceName));
|
||||
|
||||
return baseDirectory + '/' + fileList.at(resourceName);
|
||||
return (baseDirectory / fileList.at(resourceName)).string();
|
||||
}
|
||||
|
||||
std::unordered_set<ResourceID> CFilesystemLoader::getFilteredFiles(std::function<bool(const ResourceID &)> filter) const
|
||||
@ -45,7 +47,8 @@ std::unordered_set<ResourceID> CFilesystemLoader::getFilteredFiles(std::function
|
||||
{
|
||||
if (filter(file.first))
|
||||
foundID.insert(file.first);
|
||||
} return foundID;
|
||||
}
|
||||
return foundID;
|
||||
}
|
||||
|
||||
bool CFilesystemLoader::createResource(std::string filename, bool update)
|
||||
@ -65,7 +68,7 @@ bool CFilesystemLoader::createResource(std::string filename, bool update)
|
||||
|
||||
if (!update)
|
||||
{
|
||||
std::ofstream newfile (baseDirectory + "/" + filename);
|
||||
bfs::ofstream newfile(baseDirectory / filename);
|
||||
if (!newfile.good())
|
||||
return false;
|
||||
}
|
||||
@ -73,49 +76,72 @@ bool CFilesystemLoader::createResource(std::string filename, bool update)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unordered_map<ResourceID, std::string> CFilesystemLoader::listFiles(const std::string &mountPoint, size_t depth, bool initial) const
|
||||
std::unordered_map<ResourceID, bfs::path> CFilesystemLoader::listFiles(const std::string &mountPoint, size_t depth, bool initial) const
|
||||
{
|
||||
std::set<EResType::Type> initialTypes;
|
||||
initialTypes.insert(EResType::DIRECTORY);
|
||||
initialTypes.insert(EResType::TEXT);
|
||||
initialTypes.insert(EResType::ARCHIVE_LOD);
|
||||
initialTypes.insert(EResType::ARCHIVE_VID);
|
||||
initialTypes.insert(EResType::ARCHIVE_SND);
|
||||
initialTypes.insert(EResType::ARCHIVE_ZIP);
|
||||
static const EResType::Type initArray[] = {
|
||||
EResType::DIRECTORY,
|
||||
EResType::TEXT,
|
||||
EResType::ARCHIVE_LOD,
|
||||
EResType::ARCHIVE_VID,
|
||||
EResType::ARCHIVE_SND,
|
||||
EResType::ARCHIVE_ZIP };
|
||||
static const std::set<EResType::Type> initialTypes(initArray, initArray + ARRAY_COUNT(initArray));
|
||||
|
||||
assert(boost::filesystem::is_directory(baseDirectory));
|
||||
std::unordered_map<ResourceID, std::string> fileList;
|
||||
assert(bfs::is_directory(baseDirectory));
|
||||
std::unordered_map<ResourceID, bfs::path> fileList;
|
||||
|
||||
std::vector<std::string> path;//vector holding relative path to our file
|
||||
std::vector<bfs::path> path; //vector holding relative path to our file
|
||||
|
||||
boost::filesystem::recursive_directory_iterator enddir;
|
||||
boost::filesystem::recursive_directory_iterator it(baseDirectory, boost::filesystem::symlink_option::recurse);
|
||||
bfs::recursive_directory_iterator enddir;
|
||||
bfs::recursive_directory_iterator it(baseDirectory, bfs::symlink_option::recurse);
|
||||
|
||||
for(; it != enddir; ++it)
|
||||
{
|
||||
EResType::Type type;
|
||||
|
||||
if (boost::filesystem::is_directory(it->status()))
|
||||
if (bfs::is_directory(it->status()))
|
||||
{
|
||||
path.resize(it.level()+1);
|
||||
path.back() = it->path().leaf().string();
|
||||
path.resize(it.level() + 1);
|
||||
path.back() = it->path().filename();
|
||||
// don't iterate into directory if depth limit reached
|
||||
it.no_push(depth <= it.level());
|
||||
|
||||
type = EResType::DIRECTORY;
|
||||
}
|
||||
else
|
||||
type = EResTypeHelper::getTypeFromExtension(boost::filesystem::extension(*it));
|
||||
type = EResTypeHelper::getTypeFromExtension(it->path().extension().string());
|
||||
|
||||
if (!initial || vstd::contains(initialTypes, type))
|
||||
{
|
||||
//reconstruct relative filename (not possible via boost AFAIK)
|
||||
std::string filename;
|
||||
for (size_t i=0; i<it.level() && i<path.size(); i++)
|
||||
filename += path[i] + '/';
|
||||
filename += it->path().leaf().string();
|
||||
bfs::path filename;
|
||||
const size_t iterations = std::min((size_t)it.level(), path.size());
|
||||
if (iterations)
|
||||
{
|
||||
filename = path.front();
|
||||
for (size_t i = 1; i < iterations; ++i)
|
||||
filename /= path[i];
|
||||
filename /= it->path().filename();
|
||||
}
|
||||
else
|
||||
filename = it->path().filename();
|
||||
|
||||
fileList[ResourceID(mountPoint + filename, type)] = filename;
|
||||
std::string resName;
|
||||
if (bfs::path::preferred_separator != '/')
|
||||
{
|
||||
// resource names are using UNIX slashes (/)
|
||||
resName.reserve(resName.size() + filename.native().size());
|
||||
resName = mountPoint;
|
||||
for (const char c : filename.string())
|
||||
if (c != bfs::path::preferred_separator)
|
||||
resName.push_back(c);
|
||||
else
|
||||
resName.push_back('/');
|
||||
}
|
||||
else
|
||||
resName = mountPoint + filename.string();
|
||||
|
||||
fileList[ResourceID(resName, type)] = std::move(filename);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ public:
|
||||
*
|
||||
* @throws std::runtime_error if the base directory is not a directory or if it is not available
|
||||
*/
|
||||
explicit CFilesystemLoader(const std::string & mountPoint, const std::string & baseDirectory, size_t depth = 16, bool initial = false);
|
||||
explicit CFilesystemLoader(std::string mountPoint, boost::filesystem::path baseDirectory, size_t depth = 16, bool initial = false);
|
||||
|
||||
/// Interface implementation
|
||||
/// @see ISimpleResourceLoader
|
||||
@ -39,11 +39,11 @@ public:
|
||||
std::string getMountPoint() const override;
|
||||
bool createResource(std::string filename, bool update = false) override;
|
||||
boost::optional<std::string> getResourceName(const ResourceID & resourceName) const override;
|
||||
std::unordered_set<ResourceID> getFilteredFiles(std::function<bool(const ResourceID &)> filter) const;
|
||||
std::unordered_set<ResourceID> getFilteredFiles(std::function<bool(const ResourceID &)> filter) const override;
|
||||
|
||||
private:
|
||||
/** The base directory which is scanned and indexed. */
|
||||
std::string baseDirectory;
|
||||
boost::filesystem::path baseDirectory;
|
||||
|
||||
std::string mountPoint;
|
||||
|
||||
@ -51,7 +51,7 @@ private:
|
||||
* key = ResourceID for resource loader
|
||||
* value = name that can be used to access file
|
||||
*/
|
||||
std::unordered_map<ResourceID, std::string> fileList;
|
||||
std::unordered_map<ResourceID, boost::filesystem::path> fileList;
|
||||
|
||||
/**
|
||||
* Returns a list of pathnames denoting the files in the directory denoted by this pathname.
|
||||
@ -62,5 +62,5 @@ private:
|
||||
* @return a list of pathnames denoting the files and directories in the directory denoted by this pathname
|
||||
* The array will be empty if the directory is empty. Ptr is null if the directory doesn't exist or if it isn't a directory.
|
||||
*/
|
||||
std::unordered_map<ResourceID, std::string> listFiles(const std::string &mountPoint, size_t depth, bool initial) const;
|
||||
std::unordered_map<ResourceID, boost::filesystem::path> listFiles(const std::string &mountPoint, size_t depth, bool initial) const;
|
||||
};
|
||||
|
@ -130,19 +130,18 @@ ISimpleResourceLoader * CResourceHandler::createInitial()
|
||||
auto filename = loader->getResourceName(ID);
|
||||
if (filename)
|
||||
{
|
||||
auto dir = new CFilesystemLoader(URI + "/", *filename, depth, true);
|
||||
auto dir = new CFilesystemLoader(URI + '/', *filename, depth, true);
|
||||
initialLoader->addLoader(dir, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: CFilesystemLoader: Should take boost::filesystem::path in argument
|
||||
for (auto & path : VCMIDirs::get().dataPaths())
|
||||
{
|
||||
if (boost::filesystem::is_directory(path)) // some of system-provided paths may not exist
|
||||
initialLoader->addLoader(new CFilesystemLoader("", path.string(), 0, true), false);
|
||||
initialLoader->addLoader(new CFilesystemLoader("", path, 0, true), false);
|
||||
}
|
||||
initialLoader->addLoader(new CFilesystemLoader("", VCMIDirs::get().userDataPath().string(), 0, true), false);
|
||||
initialLoader->addLoader(new CFilesystemLoader("", VCMIDirs::get().userDataPath(), 0, true), false);
|
||||
|
||||
recurseInDir("CONFIG", 0);// look for configs
|
||||
recurseInDir("DATA", 0); // look for archives
|
||||
@ -167,10 +166,9 @@ void CResourceHandler::initialize()
|
||||
// |-saves
|
||||
// |-config
|
||||
|
||||
// TODO: CFilesystemLoader should take boost::filesystem::path
|
||||
knownLoaders["root"] = new CFilesystemList();
|
||||
knownLoaders["saves"] = new CFilesystemLoader("SAVES/", VCMIDirs::get().userSavePath().string());
|
||||
knownLoaders["config"] = new CFilesystemLoader("CONFIG/", VCMIDirs::get().userConfigPath().string());
|
||||
knownLoaders["saves"] = new CFilesystemLoader("SAVES/", VCMIDirs::get().userSavePath());
|
||||
knownLoaders["config"] = new CFilesystemLoader("CONFIG/", VCMIDirs::get().userConfigPath());
|
||||
|
||||
auto localFS = new CFilesystemList();
|
||||
localFS->addLoader(knownLoaders["saves"], true);
|
||||
|
@ -3,10 +3,7 @@
|
||||
|
||||
#include "../CConfigHandler.h"
|
||||
|
||||
CBasicLogConfigurator::CBasicLogConfigurator(const boost::filesystem::path & filePath, CConsoleHandler * const console) :
|
||||
filePath(filePath), console(console), appendToLogFile(false) {}
|
||||
|
||||
CBasicLogConfigurator::CBasicLogConfigurator(boost::filesystem::path && filePath, CConsoleHandler * const console) :
|
||||
CBasicLogConfigurator::CBasicLogConfigurator(boost::filesystem::path filePath, CConsoleHandler * const console) :
|
||||
filePath(std::move(filePath)), console(console), appendToLogFile(false) {}
|
||||
|
||||
void CBasicLogConfigurator::configureDefault()
|
||||
|
@ -22,8 +22,7 @@ class JsonNode;
|
||||
class DLL_LINKAGE CBasicLogConfigurator
|
||||
{
|
||||
public:
|
||||
CBasicLogConfigurator(const boost::filesystem::path & filePath, CConsoleHandler * const console);
|
||||
CBasicLogConfigurator(boost::filesystem::path && filePath, CConsoleHandler * const console);
|
||||
CBasicLogConfigurator(boost::filesystem::path filePath, CConsoleHandler * const console);
|
||||
|
||||
/// Configures the logging system by parsing the logging settings. It adds the console target and the file target to the global logger.
|
||||
/// Doesn't throw, but logs on success or fault.
|
||||
|
@ -1,14 +1,30 @@
|
||||
#include "StdInc.h"
|
||||
#include "CLogger.h"
|
||||
|
||||
#ifdef VCMI_ANDROID
|
||||
#include <android/log.h>
|
||||
|
||||
namespace ELogLevel
|
||||
{
|
||||
int toAndroid(ELogLevel logLevel)
|
||||
{
|
||||
switch (logLevel)
|
||||
{
|
||||
case TRACE: return ANDROID_LOG_VERBOSE;
|
||||
case DEBUG: return ANDROID_LOG_DEBUG;
|
||||
case INFO: return ANDROID_LOG_INFO;
|
||||
case WARN: return ANDROID_LOG_WARN;
|
||||
case ERROR: return ANDROID_LOG_ERROR;
|
||||
default:;
|
||||
}
|
||||
return ANDROID_LOG_UNKNOWN;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
const std::string CLoggerDomain::DOMAIN_GLOBAL = "global";
|
||||
|
||||
CLoggerDomain::CLoggerDomain(const std::string & name) : name(name)
|
||||
{
|
||||
if(name.empty())
|
||||
throw std::runtime_error("Logger domain cannot be empty.");
|
||||
}
|
||||
CLoggerDomain::CLoggerDomain(std::string && name) : name(std::move(name))
|
||||
CLoggerDomain::CLoggerDomain(std::string name) : name(std::move(name))
|
||||
{
|
||||
if (this->name.empty())
|
||||
throw std::runtime_error("Logger domain cannot be empty.");
|
||||
@ -302,15 +318,16 @@ CLogConsoleTarget::CLogConsoleTarget(CConsoleHandler * console) : console(consol
|
||||
|
||||
void CLogConsoleTarget::write(const LogRecord & record)
|
||||
{
|
||||
if(threshold > record.level) return;
|
||||
if(threshold > record.level)
|
||||
return;
|
||||
|
||||
std::string message = formatter.format(record);
|
||||
|
||||
#ifdef VCMI_ANDROID
|
||||
__android_log_print(ANDROID_LOG_INFO, "VCMI", "%s", message.c_str());
|
||||
__android_log_write(ELogLevel::toAndroid(record.level), "VCMI", message.c_str());
|
||||
#endif
|
||||
|
||||
bool printToStdErr = record.level >= ELogLevel::WARN;
|
||||
const bool printToStdErr = record.level >= ELogLevel::WARN;
|
||||
if(console)
|
||||
{
|
||||
const EConsoleTextColor::EConsoleTextColor textColor =
|
||||
@ -340,22 +357,12 @@ void CLogConsoleTarget::setFormatter(const CLogFormatter & formatter) { this->fo
|
||||
const CColorMapping & CLogConsoleTarget::getColorMapping() const { return colorMapping; }
|
||||
void CLogConsoleTarget::setColorMapping(const CColorMapping & colorMapping) { this->colorMapping = colorMapping; }
|
||||
|
||||
CLogFileTarget::CLogFileTarget(const boost::filesystem::path & filePath, bool append /*= true*/)
|
||||
: file(filePath, append ? std::ios_base::app : std::ios_base::out)
|
||||
{
|
||||
formatter.setPattern("%d %l %n [%t] - %m");
|
||||
}
|
||||
CLogFileTarget::CLogFileTarget(boost::filesystem::path && filePath, bool append /*= true*/)
|
||||
CLogFileTarget::CLogFileTarget(boost::filesystem::path filePath, bool append /*= true*/)
|
||||
: file(std::move(filePath), append ? std::ios_base::app : std::ios_base::out)
|
||||
{
|
||||
formatter.setPattern("%d %l %n [%t] - %m");
|
||||
}
|
||||
|
||||
CLogFileTarget::~CLogFileTarget()
|
||||
{
|
||||
file.close();
|
||||
}
|
||||
|
||||
void CLogFileTarget::write(const LogRecord & record)
|
||||
{
|
||||
TLockGuard _(mx);
|
||||
|
@ -19,15 +19,19 @@ class ILogTarget;
|
||||
|
||||
namespace ELogLevel
|
||||
{
|
||||
enum ELogLevel
|
||||
{
|
||||
enum ELogLevel
|
||||
{
|
||||
NOT_SET = 0,
|
||||
TRACE,
|
||||
DEBUG,
|
||||
INFO,
|
||||
WARN,
|
||||
ERROR
|
||||
};
|
||||
};
|
||||
|
||||
#ifdef VCMI_ANDROID
|
||||
int toAndroid(ELogLevel logLevel);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// The class CLoggerDomain provides convenient access to super domains from a sub domain.
|
||||
@ -36,8 +40,7 @@ class DLL_LINKAGE CLoggerDomain
|
||||
public:
|
||||
/// Constructs a CLoggerDomain with the domain designated by name.
|
||||
/// Sub-domains can be specified by separating domains by a dot, e.g. "ai.battle". The global domain is named "global".
|
||||
explicit CLoggerDomain(const std::string & name);
|
||||
explicit CLoggerDomain(std::string && name);
|
||||
explicit CLoggerDomain(std::string name);
|
||||
|
||||
const std::string& getName() const;
|
||||
CLoggerDomain getParent() const;
|
||||
@ -288,9 +291,7 @@ class DLL_LINKAGE CLogFileTarget : public ILogTarget
|
||||
public:
|
||||
/// Constructs a CLogFileTarget and opens the file designated by file_path. If the append parameter is true, the file
|
||||
/// will be appended to. Otherwise the file designated by filePath will be truncated before being opened.
|
||||
explicit CLogFileTarget(const boost::filesystem::path & file_path, bool append = true);
|
||||
explicit CLogFileTarget(boost::filesystem::path && file_path, bool append = true);
|
||||
~CLogFileTarget();
|
||||
explicit CLogFileTarget(boost::filesystem::path file_path, bool append = true);
|
||||
|
||||
const CLogFormatter & getFormatter() const;
|
||||
void setFormatter(const CLogFormatter & formatter);
|
||||
|
@ -368,19 +368,19 @@ void ERMInterpreter::scanForScripts()
|
||||
{
|
||||
using namespace boost::filesystem;
|
||||
//parser checking
|
||||
if(!exists(VCMIDirs::get().dataPaths().back() + "/Data/s/"))
|
||||
const path dataPath = VCMIDirs::get().dataPaths().back() / "Data" / "s";
|
||||
if(!exists(dataPath))
|
||||
{
|
||||
logGlobal->warnStream() << "Warning: Folder " << VCMIDirs::get().dataPaths().back() << "/Data/s/ doesn't exist!";
|
||||
logGlobal->warnStream() << "Warning: Folder " << dataPath << " doesn't exist!";
|
||||
return;
|
||||
}
|
||||
directory_iterator enddir;
|
||||
for (directory_iterator dir(VCMIDirs::get().dataPaths().back() + "/Data/s"); dir!=enddir; dir++)
|
||||
for (directory_iterator dir(dataPath); dir!=enddir; dir++)
|
||||
{
|
||||
if(is_regular(dir->status()))
|
||||
{
|
||||
std::string name = dir->path().leaf().string();
|
||||
if( boost::algorithm::ends_with(name, ".erm") ||
|
||||
boost::algorithm::ends_with(name, ".verm") )
|
||||
const std::string ext = boost::to_upper_copy(dir->path().extension().string());
|
||||
if (ext == ".ERM" || ext == ".VERM")
|
||||
{
|
||||
ERMParser ep(dir->path().string());
|
||||
FileInfo * finfo = new FileInfo;
|
||||
|
@ -22,7 +22,7 @@
|
||||
CVcmiTestConfig::CVcmiTestConfig()
|
||||
{
|
||||
console = new CConsoleHandler;
|
||||
CBasicLogConfigurator logConfig(VCMIDirs::get().userCachePath() + "/VCMI_Test_log.txt", console);
|
||||
CBasicLogConfigurator logConfig(VCMIDirs::get().userCachePath() / "VCMI_Test_log.txt", console);
|
||||
logConfig.configureDefault();
|
||||
preinitDLL(console);
|
||||
settings.init();
|
||||
|
Loading…
Reference in New Issue
Block a user