Merge pull request #449 from Wargus/filesystem

Use more `fs::path`
This commit is contained in:
Joris Dauphin 2023-08-04 18:48:53 +02:00 committed by GitHub
commit 31da98aba2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 228 additions and 408 deletions

View file

@ -551,6 +551,7 @@ set(stratagus_generic_HDRS
src/include/depend.h
src/include/editor.h
src/include/online_service.h
src/include/filesystem.h
src/include/font.h
src/include/fov.h
src/include/fow.h
@ -558,7 +559,6 @@ set(stratagus_generic_HDRS
src/include/game.h
src/include/icons.h
src/include/interface.h
src/include/iocompat.h
src/include/iolib.h
src/include/luacallback.h
src/include/map.h

View file

@ -63,7 +63,6 @@
#include "commands.h"
#include "game.h"
#include "interface.h"
#include "iocompat.h"
#include "luacallback.h"
#include "map.h"
#include "missile.h"
@ -486,26 +485,19 @@ static void DumpUnitInfo(CUnit &unit)
time_t now;
time(&now);
std::string path(Parameters::Instance.GetUserDirectory());
fs::path path(Parameters::Instance.GetUserDirectory());
if (!GameName.empty()) {
path += "/";
path += GameName;
}
path += "/logs";
struct stat tmp;
if (stat(path.c_str(), &tmp) < 0) {
makedir(path.c_str(), 0777);
path /= GameName;
}
path /= "logs";
fs::create_directories(path);
path += "/unit_log_of_stratagus_";
path += std::to_string(ThisPlayer->Index);
path += "_";
path += std::to_string((intmax_t)now);
path += ".log";
path /= "unit_log_of_stratagus_" + std::to_string(ThisPlayer->Index) + "_"
+ std::to_string((intmax_t) now) + ".log";
logf = fopen(path.c_str(), "wb");
logf = fopen(path.string().c_str(), "wb");
if (!logf) {
DebugPrint("Could not open %s for writing\n" _C_ path.c_str());
DebugPrint("Could not open %s for writing\n" _C_ path.string().c_str());
return ;
}
fprintf(logf, "; Log file generated by Stratagus Version " VERSION "\n");

View file

@ -46,7 +46,6 @@
#include "game.h"
#include "guichan.h"
#include "interface.h"
#include "iocompat.h"
#include "iolib.h"
#include "map.h"
#include "menus.h"
@ -1882,15 +1881,15 @@ static void EditorCallbackExit()
void CEditor::Init()
{
// Load and evaluate the editor configuration file
const std::string filename = LibraryFileName(Parameters::Instance.luaEditorStartFilename.c_str());
if (access(filename.c_str(), R_OK)) {
const fs::path filename = LibraryFileName(Parameters::Instance.luaEditorStartFilename.c_str());
if (!fs::exists(filename)) {
fprintf(stderr, "Editor configuration file '%s' was not found\n"
"Specify another with '-E file.lua'\n",
Parameters::Instance.luaEditorStartFilename.c_str());
ExitFatal(-1);
}
ShowLoadProgress(_("Script %s"), filename.c_str());
ShowLoadProgress(_("Script %s"), filename.string().c_str());
LuaLoadFile(filename);
LuaGarbageCollect();

View file

@ -49,7 +49,6 @@
#include "editor.h"
#include "font.h"
#include "interface.h"
#include "iocompat.h"
#include "iolib.h"
#include "map.h"
#include "minimap.h"
@ -182,47 +181,19 @@ void FreeAllContainers()
*/
static void LoadStratagusMap(const std::string &smpname, const std::string &mapname)
{
char mapfull[PATH_MAX];
CFile file;
fs::path mapfull = mapname;
// Try the same directory as the smp file first
strcpy_s(mapfull, sizeof(mapfull), smpname.c_str());
char *p = strrchr(mapfull, '/');
if (!p) {
p = mapfull;
} else {
++p;
}
strcpy_s(p, sizeof(mapfull) - (p - mapfull), mapname.c_str());
if (file.open(mapfull, CL_OPEN_READ) == -1) {
// Not found, try StratagusLibPath and the smp's dir
strcpy_s(mapfull, sizeof(mapfull), StratagusLibPath.c_str());
strcat_s(mapfull, sizeof(mapfull), "/");
strcat_s(mapfull, sizeof(mapfull), smpname.c_str());
char *p = strrchr(mapfull, '/');
if (!p) {
p = mapfull;
} else {
++p;
}
strcpy_s(p, sizeof(mapfull) - (p - mapfull), mapname.c_str());
if (file.open(mapfull, CL_OPEN_READ) == -1) {
// Not found again, try StratagusLibPath
strcpy_s(mapfull, sizeof(mapfull), StratagusLibPath.c_str());
strcat_s(mapfull, sizeof(mapfull), "/");
strcat_s(mapfull, sizeof(mapfull), mapname.c_str());
if (file.open(mapfull, CL_OPEN_READ) == -1) {
// Not found, try mapname by itself as a last resort
strcpy_s(mapfull, sizeof(mapfull), mapname.c_str());
} else {
file.close();
for (auto candidate : {fs::path(smpname).parent_path() / mapname,
fs::path(StratagusLibPath) / fs::path(smpname).parent_path() / mapname,
fs::path(StratagusLibPath) / mapname,
fs::path(mapname)}) {
if (fs::exists(candidate)) {
mapfull = candidate;
break;
}
} else {
file.close();
}
} else {
file.close();
}
if (LcmPreventRecurse) {
@ -232,7 +203,7 @@ static void LoadStratagusMap(const std::string &smpname, const std::string &mapn
InitPlayers();
LcmPreventRecurse = 1;
if (LuaLoadFile(mapfull) == -1) {
fprintf(stderr, "Can't load lua file: %s\n", mapfull);
fprintf(stderr, "Can't load lua file: %s\n", mapfull.string().c_str());
ExitFatal(-1);
}
LcmPreventRecurse = 0;
@ -252,7 +223,7 @@ static void LoadStratagusMap(const std::string &smpname, const std::string &mapn
}
// Write a small image of map preview
static void WriteMapPreview(const char *mapname, CMap &map)
static void WriteMapPreview(const fs::path &mapname, CMap &map)
{
const int rectSize = 5; // size of rectange used for player start spots
const SDL_PixelFormat *fmt = MinimapSurface->format;
@ -273,7 +244,7 @@ static void WriteMapPreview(const char *mapname, CMap &map)
}
SDL_UnlockSurface(preview);
IMG_SavePNG(preview, mapname);
IMG_SavePNG(preview, mapname.string().c_str());
SDL_FreeSurface(preview);
}
@ -345,12 +316,12 @@ static int WriteMapPresentation(const std::string &mapname, CMap &map, Vec2i new
** @param map map to save
** @param writeTerrain write the tiles map in the .sms
*/
int WriteMapSetup(const char *mapSetup, CMap &map, int writeTerrain, Vec2i newSize, Vec2i offset)
static int WriteMapSetup(const fs::path &mapSetup, CMap &map, int writeTerrain, Vec2i newSize, Vec2i offset)
{
FileWriter *f = nullptr;
try {
f = CreateFileWriter(mapSetup);
f = CreateFileWriter(mapSetup.string());
f->printf("-- Stratagus Map Setup\n");
f->printf("-- File generated by the Stratagus V" VERSION " builtin map editor.\n");
@ -360,7 +331,7 @@ int WriteMapSetup(const char *mapSetup, CMap &map, int writeTerrain, Vec2i newSi
f->printf("-- preamble\n");
f->printf("if CanAccessFile(__file__ .. \".preamble\") then Load(__file__ .. \".preamble\", Editor.Running == 0) end\n\n");
if (!Map.Info.Preamble.empty()) {
FileWriter *preamble = CreateFileWriter(std::string(mapSetup) + ".preamble");
FileWriter *preamble = CreateFileWriter(mapSetup.string() + ".preamble");
preamble->write(Map.Info.Preamble.c_str(), Map.Info.Preamble.size());
delete preamble;
}
@ -516,13 +487,13 @@ int WriteMapSetup(const char *mapSetup, CMap &map, int writeTerrain, Vec2i newSi
f->printf("-- postamble\n");
f->printf("if CanAccessFile(__file__ .. \".postamble\") then Load(__file__ .. \".postamble\", Editor.Running == 0) end\n\n");
if (!Map.Info.Postamble.empty()) {
FileWriter *postamble = CreateFileWriter(std::string(mapSetup) + ".postamble");
FileWriter *postamble = CreateFileWriter(mapSetup.string() + ".postamble");
postamble->write(Map.Info.Postamble.c_str(), Map.Info.Postamble.size());
delete postamble;
}
} catch (const FileException &) {
fprintf(stderr, "Can't save map setup : '%s' \n", mapSetup);
fprintf(stderr, "Can't save map setup : '%s' \n", mapSetup.string().c_str());
delete f;
return -1;
}
@ -547,25 +518,26 @@ int SaveStratagusMap(const std::string &mapName, CMap &map, int writeTerrain, Ve
ExitFatal(-1);
}
char mapSetup[PATH_MAX];
strcpy_s(mapSetup, sizeof(mapSetup), mapName.c_str());
char *setupExtension = strstr(mapSetup, ".smp");
if (!setupExtension) {
std::string extraExtension; // typically compression extension
fs::path mapSetup = mapName;
while (mapSetup.has_extension() && mapSetup.extension() != ".smp") {
extraExtension = mapSetup.extension().string() + extraExtension;
mapSetup.replace_extension();
}
if (mapSetup.extension() != ".smp") {
fprintf(stderr, "%s: invalid Stratagus map filename\n", mapName.c_str());
return -1;
}
char previewName[PATH_MAX];
strcpy_s(previewName, sizeof(previewName), mapName.c_str());
char *previewExtension = strstr(previewName, ".smp");
memcpy(previewExtension, ".png\0", 5 * sizeof(char));
fs::path previewName = mapSetup;
previewName.replace_extension(".png");
WriteMapPreview(previewName, map);
memcpy(setupExtension, ".sms", 4 * sizeof(char));
if (WriteMapPresentation(mapName, map, newSize) == -1) {
return -1;
}
mapSetup.replace_extension(".sms" + extraExtension);
return WriteMapSetup(mapSetup, map, writeTerrain, newSize, offset);
}
@ -1166,8 +1138,7 @@ static int CclSetGameName(lua_State *l)
}
if (!GameName.empty()) {
std::string path = Parameters::Instance.GetUserDirectory() + "/" + GameName;
makedir(path.c_str(), 0777);
fs::create_directories(Parameters::Instance.GetUserDirectory() / GameName);
}
return 0;
}

View file

@ -40,7 +40,6 @@
#include "commands.h"
#include "game.h"
#include "interface.h"
#include "iocompat.h"
#include "iolib.h"
#include "map.h"
#include "netconnect.h"
@ -57,6 +56,7 @@
#include "version.h"
#include <sstream>
#include <sys/stat.h>
#include <time.h>
extern void ExpandPath(std::string &newpath, const std::string &path);
@ -371,34 +371,27 @@ void CommandLog(const char *action, const CUnit *unit, int flush,
if (!LogFile) {
time_t now;
time(&now);
struct stat tmp;
std::string path(Parameters::Instance.GetUserDirectory());
fs::path path(Parameters::Instance.GetUserDirectory());
if (!GameName.empty()) {
path += "/";
path += GameName;
path /= GameName;
}
path += "/logs";
path /= "logs";
if (stat(path.c_str(), &tmp) < 0) {
makedir(path.c_str(), 0777);
}
fs::create_directories(path);
path += "/log_of_stratagus_";
path += std::to_string(ThisPlayer->Index);
path += "_";
path += std::to_string((intmax_t)now);
path += ".log";
path /= "/log_of_stratagus_" + std::to_string(ThisPlayer->Index) + "_"
+ std::to_string((intmax_t) now) + ".log";
LogFile = new CFile;
if (LogFile->open(path.c_str(), CL_OPEN_WRITE) == -1) {
if (LogFile->open(path.string().c_str(), CL_OPEN_WRITE) == -1) {
// don't retry for each command
CommandLogDisabled = false;
delete LogFile;
LogFile = nullptr;
return;
}
LastLogFileName = path;
LastLogFileName = path.string();
if (CurrentReplay) {
SaveFullLog(*LogFile);
}
@ -909,7 +902,6 @@ int SaveReplay(const std::string &filename)
{
FILE *fd;
char *buf;
std::string destination;
struct stat sb;
size_t size;
@ -918,7 +910,7 @@ int SaveReplay(const std::string &filename)
return -1;
}
destination = Parameters::Instance.GetUserDirectory() + "/" + GameName + "/logs/" + filename;
auto destination = Parameters::Instance.GetUserDirectory() / GameName / "logs" / filename;
if (!LastLogFileName.empty() && stat(LastLogFileName.c_str(), &sb)) {
fprintf(stderr, "stat failed\n");
@ -938,9 +930,9 @@ int SaveReplay(const std::string &filename)
size = fread(buf, sb.st_size, 1, fd);
fclose(fd);
fd = fopen(destination.c_str(), "wb");
fd = fopen(destination.string().c_str(), "wb");
if (!fd) {
fprintf(stderr, "Can't save to '%s'\n", destination.c_str());
fprintf(stderr, "Can't save to '%s'\n", destination.string().c_str());
delete[] buf;
return -1;
}

View file

@ -39,7 +39,6 @@
#include "actions.h"
#include "ai.h"
#include "iocompat.h"
#include "iolib.h"
#include "map.h"
#include "missile.h"
@ -71,7 +70,7 @@ extern void StartMap(const std::string &filename, bool clean);
void ExpandPath(std::string &newpath, const std::string &path)
{
if (path[0] == '~') {
newpath = Parameters::Instance.GetUserDirectory();
newpath = Parameters::Instance.GetUserDirectory().string();
if (!GameName.empty()) {
newpath += "/";
newpath += GameName;
@ -85,18 +84,14 @@ void ExpandPath(std::string &newpath, const std::string &path)
/**
** Get the save directory and create dirs if needed
*/
static std::string GetSaveDir()
static fs::path GetSaveDir()
{
struct stat tmp;
std::string dir(Parameters::Instance.GetUserDirectory());
fs::path dir(Parameters::Instance.GetUserDirectory());
if (!GameName.empty()) {
dir += "/";
dir += GameName;
}
dir += "/save";
if (stat(dir.c_str(), &tmp) < 0) {
makedir(dir.c_str(), 0777);
dir /= GameName;
}
dir /= "save";
fs::create_directories(dir);
return dir;
}
@ -111,11 +106,10 @@ static std::string GetSaveDir()
int SaveGame(const std::string &filename)
{
CFile file;
std::string fullpath(GetSaveDir());
fs::path fullpath(GetSaveDir());
fullpath += "/";
fullpath += filename;
if (file.open(fullpath.c_str(), CL_WRITE_GZ | CL_OPEN_WRITE) == -1) {
fullpath /= filename;
if (file.open(fullpath.string().c_str(), CL_WRITE_GZ | CL_OPEN_WRITE) == -1) {
fprintf(stderr, "Can't save to '%s'\n", filename.c_str());
return -1;
}
@ -195,9 +189,9 @@ void DeleteSaveGame(const std::string &filename)
return;
}
std::string fullpath = GetSaveDir() + "/" + filename;
if (unlink(fullpath.c_str()) == -1) {
fprintf(stderr, "delete failed for %s", fullpath.c_str());
fs::path fullpath = GetSaveDir() / filename;
if (unlink(fullpath.string().c_str()) == -1) {
fprintf(stderr, "delete failed for %s", fullpath.string().c_str());
}
}

View file

@ -8,9 +8,9 @@
// T H E W A R B E G I N S
// Stratagus - A free fantasy real time strategy game engine
//
/**@name iocompat.h - IO platform compatibility header file. */
/**@name filesystem - filesystem header selection. */
//
// (c) Copyright 2002-2005 by Andreas Arens
// (c) Copyright 1998-2023 by Lutz Sammer, Jimmy Salmon and Joris Dauphin.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@ -27,54 +27,25 @@
// 02111-1307, USA.
//
#ifndef __IOCOMPAT_H__
#define __IOCOMPAT_H__
#ifndef __FILESYSTEM_H__
#define __FILESYSTEM_H__
//@{
/*----------------------------------------------------------------------------
-- Platform dependent IO-related Includes and Definitions
-- Includes
----------------------------------------------------------------------------*/
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#ifdef _MSC_VER
#include <io.h>
#include <fcntl.h>
#include <direct.h>
#define R_OK 4
#define F_OK 0
#define PATH_MAX _MAX_PATH
#define S_ISDIR(x) ((x) & _S_IFDIR)
#define S_ISREG(x) ((x) & _S_IFREG)
#define mkdir _mkdir
#define access _access
#if __has_include(<filesystem>)
# include <filesystem>
namespace fs = std::filesystem;
#elif __has_include(<experimental/filesystem>)
# include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#else
#include <unistd.h>
#include <dirent.h>
#endif
#ifndef O_BINARY
#define O_BINARY 0
#endif
#ifdef USE_WIN32
#define makedir(dir, permissions) mkdir(dir)
#else
#define makedir(dir, permissions) mkdir(dir, permissions)
error "Missing the <filesystem> header."
#endif
//@}
#endif // !__IOCOMPAT_H__
#endif /* __FILESYSTEM_H__ */

View file

@ -37,6 +37,7 @@
----------------------------------------------------------------------------*/
#include <vector>
#include "filesystem.h"
#include "SDL.h"
/*----------------------------------------------------------------------------
@ -144,7 +145,7 @@ extern std::string LibraryFileName(const char *file);
extern bool CanAccessFile(const char *filename);
/// Read the contents of a directory
extern int ReadDataDirectory(const char *dirname, std::vector<FileList> &flp);
extern std::vector<FileList> ReadDataDirectory(const fs::path& directory);
extern std::vector<std::string> QuoteArguments(const std::vector<std::string>& args);
extern std::vector<std::wstring> QuoteArguments(const std::vector<std::wstring>& args);

View file

@ -36,14 +36,14 @@ public:
void SetDefaultValues();
void SetLocalPlayerNameFromEnv();
void SetUserDirectory(const std::string &path) {
if (path.size() == 0) {
void SetUserDirectory(const fs::path& path) {
if (path.empty()) {
SetDefaultUserDirectory(true);
} else {
userDirectory = path;
}
}
const std::string &GetUserDirectory() const { return userDirectory; }
const fs::path& GetUserDirectory() const { return userDirectory; }
private:
void SetDefaultUserDirectory(bool noPortable = false);
@ -56,7 +56,7 @@ public:
std::string LocalPlayerName; /// Name of local player
bool benchmark = false; /// If true, run as fast as possible and report fps at the end of a game
private:
std::string userDirectory; /// Directory containing user settings and data
fs::path userDirectory; /// Directory containing user settings and data
public:
static Parameters Instance;
};

View file

@ -47,6 +47,9 @@ extern "C" {
}
#endif
#include "filesystem.h"
#include "stratagus.h"
/*----------------------------------------------------------------------------
-- Declarations
----------------------------------------------------------------------------*/
@ -74,7 +77,7 @@ extern int lua_isstring_strict(lua_State *luaStack, int idx);
extern lua_State *Lua;
extern int LuaLoadFile(const std::string &file, const std::string &strArg = "", bool exitOnError = true);
extern int LuaLoadFile(const fs::path &file, const std::string &strArg = "", bool exitOnError = true);
extern int LuaCall(int narg, int clear, bool exitOnError = true);
extern int LuaCall(lua_State *L, int narg, int nresults, int base, bool exitOnError = true);

View file

@ -32,15 +32,7 @@
//@{
#if __has_include(<filesystem>)
#include <filesystem>
namespace fs = std::filesystem;
#elif __has_include(<experimental/filesystem>)
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#else
error "Missing the <filesystem> header."
#endif
#include "filesystem.h"
#include <cstdlib>
#include <cstdint>

View file

@ -188,7 +188,7 @@ private:
void ExpandFor(const uint16_t numOfFramesToAdd);
public:
std::string File; /// Filename
fs::path File; /// Filename
std::string HashFile; /// Filename used in hash
SDL_Surface *Surface; /// Surface
SDL_Surface *SurfaceFlip; /// Flipped surface

View file

@ -862,7 +862,7 @@ static int CclLoadTileModels(lua_State *l)
LuaError(l, "incorrect argument");
}
Map.TileModelsFileName = LuaToString(l, 1);
const std::string filename = LibraryFileName(Map.TileModelsFileName.c_str());
const fs::path filename = LibraryFileName(Map.TileModelsFileName.c_str());
if (LuaLoadFile(filename) == -1) {
DebugPrint("Load failed: %s\n" _C_ filename.c_str());
}

View file

@ -42,16 +42,8 @@
#include <array>
#include <utility>
#include <random>
#if __has_include(<filesystem>)
#include <filesystem>
namespace fs = std::filesystem;
#elif __has_include(<experimental/filesystem>)
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#else
error "Missing the <filesystem> header."
#endif
#include "filesystem.h"
#include "game.h"
#include "online_service.h"
#include "stratagus.h"

View file

@ -45,7 +45,6 @@
#include "fluidsynth.h"
#endif
#include "iocompat.h"
#include "iolib.h"
#include "unit.h"
@ -425,8 +424,8 @@ static Mix_Chunk *LoadSample(const char *name)
*/
Mix_Music *LoadMusic(const std::string &name)
{
const std::string filename = LibraryFileName(name.c_str());
Mix_Music *music = LoadMusic(filename.c_str());
const fs::path filename = LibraryFileName(name.c_str());
Mix_Music *music = LoadMusic(filename.string().c_str());
if (music == nullptr) {
fprintf(stderr, "Can't load the music '%s'\n", name.c_str());
@ -445,8 +444,8 @@ Mix_Music *LoadMusic(const std::string &name)
*/
Mix_Chunk *LoadSample(const std::string &name)
{
const std::string filename = LibraryFileName(name.c_str());
Mix_Chunk *sample = LoadSample(filename.c_str());
const fs::path filename = LibraryFileName(name.c_str());
Mix_Chunk *sample = LoadSample(filename.string().c_str());
if (sample == nullptr) {
fprintf(stderr, "Can't load the sound '%s': %s\n", name.c_str(), Mix_GetError());

View file

@ -39,7 +39,6 @@
#include "iolib.h"
#include "game.h"
#include "iocompat.h"
#include "map.h"
#include "parameters.h"
#include "util.h"
@ -546,31 +545,29 @@ long CFile::PImpl::tell()
/**
** Find a file with its correct extension ("", ".gz" or ".bz2")
**
** @param file The string with the file path. Upon success, the string
** @param fullpath the file path. Upon success, the path
** is replaced by the full filename with the correct extension.
** @param filesize Size of the file buffer
**
** @return true if the file has been found.
*/
static bool FindFileWithExtension(char(&file)[PATH_MAX])
static bool FindFileWithExtension(fs::path &fullpath)
{
if (!access(file, R_OK)) {
if (fs::exists(fullpath)) {
return true;
}
#if defined(USE_ZLIB) || defined(USE_BZ2LIB)
char buf[PATH_MAX + 4];
auto directory = fullpath.parent_path();
auto filename = fullpath.filename().string();
#endif
#ifdef USE_ZLIB // gzip or bzip2 in global shared directory
snprintf(buf, PATH_MAX, "%s.gz", file);
if (!access(buf, R_OK)) {
strcpy_s(file, PATH_MAX, buf);
if (fs::exists(directory / (filename + ".gz"))) {
fullpath = directory / (filename + ".gz");
return true;
}
#endif
#ifdef USE_BZ2LIB
snprintf(buf, PATH_MAX, "%s.bz2", file);
if (!access(buf, R_OK)) {
strcpy_s(file, PATH_MAX, buf);
if (fs::exists(directory / (filename + ".bz2"))) {
fullpath = directory / (filename + ".bz2");
return true;
}
#endif
@ -584,95 +581,81 @@ static bool FindFileWithExtension(char(&file)[PATH_MAX])
** This supports .gz, .bz2 and .zip.
**
** @param file Filename to open.
** @param buffer Allocated buffer for generated filename.
** return generated filename.
*/
static void LibraryFileName(const char *file, char(&buffer)[PATH_MAX])
static fs::path LibraryFileNameImpl(const char *file)
{
// Absolute path or in current directory.
strcpy_s(buffer, PATH_MAX, file);
if (*buffer == '/') {
return;
fs::path candidate = file;
if (candidate.is_absolute()) {
return candidate;
}
if (FindFileWithExtension(buffer)) {
return;
if (FindFileWithExtension(candidate)) {
return candidate;
}
// Try in map directory
if (*CurrentMapPath) {
if (*CurrentMapPath == '.' || *CurrentMapPath == '/') {
strcpy_s(buffer, PATH_MAX, CurrentMapPath);
char *s = strrchr(buffer, '/');
if (s) {
s[1] = '\0';
}
strcat_s(buffer, PATH_MAX, file);
candidate = fs::path(CurrentMapPath) / file;
} else {
strcpy_s(buffer, PATH_MAX, StratagusLibPath.c_str());
if (*buffer) {
strcat_s(buffer, PATH_MAX, "/");
candidate = fs::path(StratagusLibPath) / CurrentMapPath / file;
}
strcat_s(buffer, PATH_MAX, CurrentMapPath);
char *s = strrchr(buffer, '/');
if (s) {
s[1] = '\0';
}
strcat_s(buffer, PATH_MAX, file);
}
if (FindFileWithExtension(buffer)) {
return;
if (FindFileWithExtension(candidate)) {
return candidate;
}
}
// In user home directory
if (!GameName.empty()) {
sprintf(buffer, "%s/%s/%s", Parameters::Instance.GetUserDirectory().c_str(), GameName.c_str(), file);
if (FindFileWithExtension(buffer)) {
return;
candidate = Parameters::Instance.GetUserDirectory() / GameName / file;
if (FindFileWithExtension(candidate)) {
return candidate;
}
}
// In global shared directory
sprintf(buffer, "%s/%s", StratagusLibPath.c_str(), file);
if (FindFileWithExtension(buffer)) {
return;
candidate = fs::path(StratagusLibPath) / file;
if (FindFileWithExtension(candidate)) {
return candidate;
}
// Support for graphics in default graphics dir.
// They could be anywhere now, but check if they haven't
// got full paths.
sprintf(buffer, "graphics/%s", file);
if (FindFileWithExtension(buffer)) {
return;
candidate = fs::path("graphics") / file;
if (FindFileWithExtension(candidate)) {
return candidate;
}
sprintf(buffer, "%s/graphics/%s", StratagusLibPath.c_str(), file);
if (FindFileWithExtension(buffer)) {
return;
candidate = fs::path(StratagusLibPath) / "graphics" / file;
if (FindFileWithExtension(candidate)) {
return candidate;
}
// Support for sounds in default sounds dir.
// They could be anywhere now, but check if they haven't
// got full paths.
sprintf(buffer, "sounds/%s", file);
if (FindFileWithExtension(buffer)) {
return;
candidate = fs::path("sounds") / file;
if (FindFileWithExtension(candidate)) {
return candidate;
}
sprintf(buffer, "%s/sounds/%s", StratagusLibPath.c_str(), file);
if (FindFileWithExtension(buffer)) {
return;
candidate = fs::path(StratagusLibPath) / "sounds" / file;
if (FindFileWithExtension(candidate)) {
return candidate;
}
// Support for scripts in default scripts dir.
sprintf(buffer, "scripts/%s", file);
if (FindFileWithExtension(buffer)) {
return;
candidate = fs::path("scripts") / file;
if (FindFileWithExtension(candidate)) {
return candidate;
}
sprintf(buffer, "%s/scripts/%s", StratagusLibPath.c_str(), file);
if (FindFileWithExtension(buffer)) {
return;
candidate = fs::path(StratagusLibPath) / "scripts" / file;
if (FindFileWithExtension(candidate)) {
return candidate;
}
DebugPrint("File '%s' not found\n" _C_ file);
strcpy_s(buffer, PATH_MAX, file);
return file;
}
extern std::string LibraryFileName(const char *file)
@ -680,9 +663,8 @@ extern std::string LibraryFileName(const char *file)
static std::unordered_map<std::string, std::string> FileNameMap;
auto result = FileNameMap.find(file);
if (result == std::end(FileNameMap)) {
char buffer[PATH_MAX];
LibraryFileName(file, buffer);
std::string r(buffer);
fs::path path = LibraryFileNameImpl(file);
std::string r(path.string());
FileNameMap[file] = r;
return r;
} else {
@ -693,10 +675,8 @@ extern std::string LibraryFileName(const char *file)
bool CanAccessFile(const char *filename)
{
if (filename && filename[0] != '\0') {
char name[PATH_MAX];
name[0] = '\0';
LibraryFileName(filename, name);
return (name[0] != '\0' && 0 == access(name, R_OK));
const auto path = LibraryFileNameImpl(filename);
return fs::exists(path);
}
return false;
}
@ -705,70 +685,27 @@ bool CanAccessFile(const char *filename)
** Generate a list of files within a specified directory
**
** @param dirname Directory to read.
** @param fl Filelist pointer.
**
** @return the number of entries added to FileList.
** @return list of files/directories.
*/
int ReadDataDirectory(const char *dirname, std::vector<FileList> &fl)
std::vector<FileList> ReadDataDirectory(const fs::path& directory)
{
struct stat st;
char buffer[PATH_MAX];
char *filename;
std::vector<FileList> files;
strcpy_s(buffer, sizeof(buffer), dirname);
int n = strlen(buffer);
if (!n || buffer[n - 1] != '/') {
buffer[n++] = '/';
buffer[n] = 0;
}
char *np = buffer + n;
#ifndef USE_WIN32
DIR *dirp = opendir(dirname);
struct dirent *dp;
if (dirp) {
while ((dp = readdir(dirp)) != nullptr) {
filename = dp->d_name;
#else
strcat_s(buffer, sizeof(buffer), "*.*");
struct _finddata_t fileinfo;
intptr_t hFile = _findfirst(buffer, &fileinfo);
if (hFile != -1) {
do {
filename = fileinfo.name;
#endif
if (strcmp(filename, ".") == 0) {
continue;
}
if (strcmp(filename, "..") == 0) {
continue;
}
strcpy_s(np, sizeof(buffer) - (np - buffer), filename);
if (stat(buffer, &st) == 0) {
int isdir = S_ISDIR(st.st_mode);
if (isdir || S_ISREG(st.st_mode)) {
FileList nfl;
if (isdir) {
nfl.name = np;
} else {
nfl.name = np;
nfl.type = 1;
}
// sorted instertion
fl.insert(std::lower_bound(fl.begin(), fl.end(), nfl), nfl);
for (auto it = fs::directory_iterator{directory};
it != fs::directory_iterator{};
++it) {
if (fs::is_directory(it->path())) {
files.emplace_back();
files.back().name = it->path().filename().string();
} else if (fs::is_regular_file(it->path())) {
files.emplace_back();
files.back().name = it->path().filename().string();
files.back().type = 1;
}
}
#ifndef USE_WIN32
}
closedir(dirp);
#else
} while (_findnext(hFile, &fileinfo) == 0);
_findclose(hFile);
#endif
}
return fl.size();
std::sort(files.begin(), files.end());
return files;
}
void FileWriter::printf(const char *format, ...)

View file

@ -31,13 +31,13 @@
#include "stratagus.h"
#include "filesystem.h"
#include "parameters.h"
#include <stdlib.h>
#ifdef USE_WIN32
#include <Shlobj.h>
#include <filesystem>
#endif
/* static */ Parameters Parameters::Instance;
@ -59,7 +59,7 @@ void Parameters::SetDefaultUserDirectory(bool noPortable)
if (!noPortable) {
// if launcher is in the same directory as the data, we are in a portable install
fs::path executable_path = GetExecutablePath();
if (std::filesystem::equivalent(std::filesystem::path(StratagusLibPath), executable_path.parent_path())) {
if (fs::equivalent(fs::path(StratagusLibPath), executable_path.parent_path())) {
userDirectory = StratagusLibPath;
return;
}

View file

@ -33,26 +33,16 @@
-- Includes
----------------------------------------------------------------------------*/
#if __has_include(<filesystem>)
#include <filesystem>
namespace fs = std::filesystem;
#elif __has_include(<experimental/filesystem>)
#include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
#else
error "Missing the <filesystem> header."
#endif
#include "script.h"
#include <signal.h>
#include "stratagus.h"
#include "script.h"
#include "animation/animation_setplayervar.h"
#include "filesystem.h"
#include "font.h"
#include "game.h"
#include "iocompat.h"
#include "iolib.h"
#include "map.h"
#include "parameters.h"
@ -217,14 +207,14 @@ int LuaCall(lua_State *L, int narg, int nresults, int base, bool exitOnError)
/**
** Get the (uncompressed) content of the file into a string
*/
static bool GetFileContent(const std::string &file, std::string &content)
static bool GetFileContent(const fs::path& file, std::string &content)
{
CFile fp;
content.clear();
if (fp.open(file.c_str(), CL_OPEN_READ) == -1) {
DebugPrint("Can't open file '%s\n" _C_ file.c_str());
fprintf(stderr, "Can't open file '%s': %s\n", file.c_str(), strerror(errno));
if (fp.open(file.string().c_str(), CL_OPEN_READ) == -1) {
DebugPrint("Can't open file '%s\n" _C_ file.string().c_str());
fprintf(stderr, "Can't open file '%s': %s\n", file.string().c_str(), strerror(errno));
return false;
}
@ -254,22 +244,22 @@ static bool GetFileContent(const std::string &file, std::string &content)
**
** @return 0 for success, -1 if the file was not found, else exit.
*/
int LuaLoadFile(const std::string &file, const std::string &strArg, bool exitOnError)
int LuaLoadFile(const fs::path &file, const std::string &strArg, bool exitOnError)
{
DebugPrint("Loading '%s'\n" _C_ file.c_str());
DebugPrint("Loading '%s'\n" _C_ file.string().c_str());
std::string content;
if (GetFileContent(file, content) == false) {
return -1;
}
if (file.rfind("stratagus.lua") != -1) {
if (file.string().rfind("stratagus.lua") != -1) {
FileChecksums ^= fletcher32(content);
DebugPrint("FileChecksums after loading %s: %x\n" _C_ file.c_str() _C_ FileChecksums);
DebugPrint("FileChecksums after loading %s: %x\n" _C_ file.string().c_str() _C_ FileChecksums);
}
// save the current __file__
lua_getglobal(Lua, "__file__");
const int status = luaL_loadbuffer(Lua, content.c_str(), content.size(), file.c_str());
const int status = luaL_loadbuffer(Lua, content.c_str(), content.size(), file.string().c_str());
if (!status) {
lua_pushstring(Lua, fs::absolute(fs::path(file)).generic_u8string().c_str());
@ -313,10 +303,10 @@ static int CclLoad(lua_State *l)
if (arg < 1 || arg > 2) {
LuaError(l, "incorrect argument");
}
const std::string filename = LibraryFileName(LuaToString(l, 1));
const fs::path filename = LibraryFileName(LuaToString(l, 1));
bool exitOnError = arg == 2 ? LuaToBoolean(l, 2) : true;
if (LuaLoadFile(filename, "", exitOnError) == -1) {
DebugPrint("Load failed: %s\n" _C_ filename.c_str());
DebugPrint("Load failed: %s\n" _C_ filename.string().c_str());
}
return 0;
}
@ -331,8 +321,8 @@ static int CclLoad(lua_State *l)
static int CclLoadBuffer(lua_State *l)
{
LuaCheckArgs(l, 1);
const std::string file = LibraryFileName(LuaToString(l, 1));
DebugPrint("Loading '%s'\n" _C_ file.c_str());
const fs::path file = LibraryFileName(LuaToString(l, 1));
DebugPrint("Loading '%s'\n" _C_ file.string().c_str());
std::string content;
if (GetFileContent(file, content) == false) {
return 0;
@ -2053,30 +2043,26 @@ static int CclFilteredListDirectory(lua_State *l, int type, int mask)
if (strpbrk(userdir, ":*?\"<>|") != 0 || strstr(userdir, "..") != 0) {
LuaError(l, "Forbidden directory");
}
char directory[PATH_MAX];
fs::path dir;
if (pathtype == 1) {
++userdir;
std::string dir(Parameters::Instance.GetUserDirectory());
dir = Parameters::Instance.GetUserDirectory();
if (!GameName.empty()) {
dir += "/";
dir += GameName;
dir /= GameName;
}
snprintf(directory, sizeof(directory), "%s/%s", dir.c_str(), userdir);
dir /= userdir;
} else if (rel) {
std::string dir = LibraryFileName(userdir);
snprintf(directory, sizeof(directory), "%s", dir.c_str());
dir = LibraryFileName(userdir);
} else {
snprintf(directory, sizeof(directory), "%s/%s", StratagusLibPath.c_str(), userdir);
dir = fs::path(StratagusLibPath) / userdir;
}
lua_newtable(l);
std::vector<FileList> flp;
n = ReadDataDirectory(directory, flp);
int j = 0;
for (int i = 0; i < n; ++i) {
if ((flp[i].type & mask) == type) {
for (const auto& flp : ReadDataDirectory(dir)) {
if ((flp.type & mask) == type) {
lua_pushnumber(l, j + 1);
lua_pushstring(l, flp[i].name.c_str());
lua_pushstring(l, flp.name.c_str());
lua_settable(l, -3);
++j;
}
@ -2502,17 +2488,16 @@ void SavePreferences()
}
blockTableNames.push_back("preferences");
if (lua_type(Lua, -1) == LUA_TTABLE) {
std::string path = Parameters::Instance.GetUserDirectory();
fs::path path = Parameters::Instance.GetUserDirectory();
if (!GameName.empty()) {
path += "/";
path += GameName;
path /= GameName;
}
path += "/preferences.lua";
path /= "preferences.lua";
FILE *fd = fopen(path.c_str(), "w");
FILE *fd = fopen(path.string().c_str(), "w");
if (!fd) {
DebugPrint("Cannot open file %s for writing\n" _C_ path.c_str());
DebugPrint("Cannot open file %s for writing\n" _C_ path.string().c_str());
return;
}
@ -2532,13 +2517,13 @@ void LoadCcl(const std::string &filename, const std::string &luaArgStr)
{
// Load and evaluate configuration file
CclInConfigFile = 1;
const std::string name = LibraryFileName(filename.c_str());
if (access(name.c_str(), R_OK)) {
const fs::path name = LibraryFileName(filename.c_str());
if (!fs::exists(name)) {
fprintf(stderr, "Maybe you need to specify another gamepath with '-d /path/to/datadir'?\n");
ExitFatal(-1);
}
ShowLoadProgress(_("Script %s\n"), name.c_str());
ShowLoadProgress(_("Script %s\n"), name.string().c_str());
LuaLoadFile(name, luaArgStr);
CclInConfigFile = 0;
LuaGarbageCollect();
@ -2675,7 +2660,7 @@ static int CclListFilesystem(lua_State *l)
lua_newtable(l);
int j = 0;
for (auto const& vol: vols) {
if (!access(vol.generic_u8string().c_str(), R_OK)) {
if (fs::exists(vol)) {
lua_pushnumber(l, ++j);
lua_pushstring(l, vol.generic_u8string().c_str());
lua_settable(l, -3);
@ -2688,7 +2673,7 @@ static int CclListFilesystem(lua_State *l)
lua_newtable(l);
int j = 0;
for (auto const& dir_entry: fs::directory_iterator(fs::path(dir))) {
if ((fs::is_regular_file(dir_entry.path()) || fs::is_directory(dir_entry.path())) && !access(dir_entry.path().generic_u8string().c_str(), R_OK)) {
if ((fs::is_regular_file(dir_entry.path()) || fs::is_directory(dir_entry.path())) && fs::exists(dir_entry.path())) {
std::string name = dir_entry.path().generic_u8string();
if (fs::is_directory(dir_entry.path())) {
name += "/";

View file

@ -190,7 +190,6 @@ extern void beos_init(int argc, char **argv);
#include "game.h"
#include "guichan.h"
#include "interface.h"
#include "iocompat.h"
#include "iolib.h"
#include "map.h"
#include "netconnect.h"
@ -315,7 +314,7 @@ static int MenuLoop()
GameCursor = UI.Point.Cursor;
// FIXME delete this when switching to full guichan GUI
const std::string filename = LibraryFileName("scripts/guichan.lua");
const fs::path filename = LibraryFileName("scripts/guichan.lua");
status = LuaLoadFile(filename);
// We clean up later in Exit
@ -502,12 +501,12 @@ static void CleanupOutput()
static void RedirectOutput()
{
std::string path = Parameters::Instance.GetUserDirectory();
const auto& path = Parameters::Instance.GetUserDirectory();
makedir(path.c_str(), 0777);
fs::create_directories(path);
stdoutFile = path + "\\stdout.txt";
stderrFile = path + "\\stderr.txt";
stdoutFile = (path / "stdout.txt").string();
stderrFile = (path / "stderr.txt").string();
if (!freopen(stdoutFile.c_str(), "w", stdout)) {
printf("freopen stdout failed");
@ -743,7 +742,7 @@ int stratagusMain(int argc, char **argv)
// Init the random number generator.
InitSyncRand();
makedir(parameters.GetUserDirectory().c_str(), 0777);
fs::create_directories(parameters.GetUserDirectory());
// Init Lua and register lua functions!
InitLua();

View file

@ -83,8 +83,8 @@ void LoadPO(const char *file)
return;
}
const std::string fullfile = LibraryFileName(file);
FILE *fd = fopen(fullfile.c_str(), "rb");
const fs::path fullfile = LibraryFileName(file);
FILE *fd = fopen(fullfile.string().c_str(), "rb");
if (!fd) {
fprintf(stderr, "Could not open file: %s\n", file);
return;

View file

@ -45,7 +45,6 @@
#include "video.h"
#include "player.h"
#include "intern_video.h"
#include "iocompat.h"
#include "iolib.h"
#include "ui.h"
@ -54,7 +53,7 @@
----------------------------------------------------------------------------*/
static int HashCount;
static std::map<std::string, CGraphic *> GraphicHash;
static std::map<fs::path, CGraphic *> GraphicHash;
static std::list<CGraphic *> Graphics;
/*----------------------------------------------------------------------------
@ -424,7 +423,7 @@ CGraphic *CGraphic::New(const std::string &filename, const int w, const int h)
return new CGraphic;
}
const std::string file = LibraryFileName(filename.c_str());
const fs::path file = LibraryFileName(filename.c_str());
CGraphic *&g = GraphicHash[file];
if (g == nullptr) {
g = new CGraphic;
@ -434,7 +433,7 @@ CGraphic *CGraphic::New(const std::string &filename, const int w, const int h)
}
// FIXME: use a constructor for this
g->File = file;
g->HashFile = g->File;
g->HashFile = g->File.string();
g->Width = w;
g->Height = h;
} else {
@ -461,7 +460,7 @@ CPlayerColorGraphic *CPlayerColorGraphic::New(const std::string &filename, int w
return new CPlayerColorGraphic;
}
const std::string file = LibraryFileName(filename.c_str());
const fs::path file = LibraryFileName(filename.c_str());
CPlayerColorGraphic *g = dynamic_cast<CPlayerColorGraphic *>(GraphicHash[file]);
if (g == nullptr) {
g = new CPlayerColorGraphic;
@ -471,7 +470,7 @@ CPlayerColorGraphic *CPlayerColorGraphic::New(const std::string &filename, int w
}
// FIXME: use a constructor for this
g->File = file;
g->HashFile = g->File;
g->HashFile = g->File.string();
g->Width = w;
g->Height = h;
GraphicHash[g->HashFile] = g;
@ -519,7 +518,7 @@ CGraphic *CGraphic::ForceNew(const std::string &file, const int w, const int h)
*/
CPlayerColorGraphic *CPlayerColorGraphic::Clone(bool grayscale) const
{
CPlayerColorGraphic *g = CPlayerColorGraphic::ForceNew(this->File, this->Width, this->Height);
CPlayerColorGraphic *g = CPlayerColorGraphic::ForceNew(this->File.string(), this->Width, this->Height);
if (this->IsLoaded()) {
g->Load(grayscale);
@ -541,7 +540,7 @@ CGraphic *CGraphic::Get(const std::string &filename)
return nullptr;
}
const std::string file = LibraryFileName(filename.c_str());
const fs::path file = LibraryFileName(filename.c_str());
CGraphic *&g = GraphicHash[file];
return g;
@ -560,7 +559,7 @@ CPlayerColorGraphic *CPlayerColorGraphic::Get(const std::string &filename)
return nullptr;
}
const std::string file = LibraryFileName(filename.c_str());
const fs::path file = LibraryFileName(filename.c_str());
CPlayerColorGraphic *g = dynamic_cast<CPlayerColorGraphic *>(GraphicHash[file]);
return g;
@ -663,18 +662,18 @@ void CGraphic::Load(bool grayscale)
}
CFile fp;
const std::string name = LibraryFileName(File.c_str());
const fs::path name = LibraryFileName(File.string().c_str());
if (name.empty()) {
perror("Cannot find file");
goto error;
}
if (fp.open(name.c_str(), CL_OPEN_READ) == -1) {
if (fp.open(name.string().c_str(), CL_OPEN_READ) == -1) {
perror("Can't open file");
goto error;
}
Surface = IMG_Load_RW(fp.as_SDL_RWops(), 0);
if (Surface == nullptr) {
fprintf(stderr, "Couldn't load file %s: %s", name.c_str(), IMG_GetError());
fprintf(stderr, "Couldn't load file %s: %s", name.string().c_str(), IMG_GetError());
goto error;
}
@ -697,7 +696,7 @@ void CGraphic::Load(bool grayscale)
if ((GraphicWidth / Width) * Width != GraphicWidth ||
(GraphicHeight / Height) * Height != GraphicHeight) {
fprintf(stderr, "Invalid graphic (width, height) %s\n", File.c_str());
fprintf(stderr, "Invalid graphic (width, height) %s\n", File.string().c_str());
fprintf(stderr, "Expected: (%d,%d) Found: (%d,%d)\n",
Width, Height, GraphicWidth, GraphicHeight);
ExitFatal(-1);
@ -713,7 +712,7 @@ void CGraphic::Load(bool grayscale)
return;
error:
fprintf(stderr, "Can't load the graphic '%s'\n", File.c_str());
fprintf(stderr, "Can't load the graphic '%s'\n", File.string().c_str());
ExitFatal(-1);
}
@ -1320,10 +1319,9 @@ void CGraphic::MakeShadow(int xOffset, int yOffset)
void FreeGraphics()
{
std::map<std::string, CGraphic *>::iterator i;
while (!GraphicHash.empty()) {
i = GraphicHash.begin();
CGraphic::Free((*i).second);
auto it = GraphicHash.begin();
CGraphic::Free((*it).second);
}
}

View file

@ -39,7 +39,6 @@
#include "video.h"
#include "iolib.h"
#include "iocompat.h"
/*----------------------------------------------------------------------------
-- Variables

View file

@ -45,7 +45,6 @@
#include "movie.h"
#include "iocompat.h"
#include "iolib.h"
#include "network.h"
#include "sound.h"

View file

@ -39,7 +39,6 @@
#include "map.h"
#include "video.h"
#include "iolib.h"
#include "iocompat.h"
/*----------------------------------------------------------------------------
-- Variables

View file

@ -213,7 +213,6 @@ static int loadShaders() {
COMPILE_BUILTIN_SHADER(VHS);
#undef COMPILE_BUILTIN_SHADER
std::vector<FileList> flp;
fs::path shaderPath(StratagusLibPath);
shaderPath /= "shaders";
#ifdef _WIN32
@ -229,14 +228,13 @@ static int loadShaders() {
ExpandEnvironmentStrings(shaderPathStr.c_str(), cShaderPath, fullpathsize);
shaderPath = cShaderPath;
#endif
int n = ReadDataDirectory(shaderPath.string().c_str(), flp);
for (int i = 0; i < n; ++i) {
int pos = flp[i].name.find(".glsl");
for (const auto& flp : ReadDataDirectory(shaderPath)) {
int pos = flp.name.find(".glsl");
if (pos > 0) {
GLuint program = compileProgram((shaderPath / flp[i].name).string());
GLuint program = compileProgram((shaderPath / flp.name).string());
if (program) {
shaderPrograms[numShdr] = program;
shaderNames[numShdr] = strdup(flp[i].name.c_str());
shaderNames[numShdr] = strdup(flp.name.c_str());
numShdr += 1;
if (numShdr >= MAX_SHADERS) {
break;