path improvements/fixes:

- replace more std::wstring with Native or VfsPath; wstring_from_utf8 ->
NativePathFromString
- replace sequences of Join(Path(), Basename+extension) with
ChangeExtension in wsdl, CacheLoader
- add Path::IsDirectory to replace .empty() / path_is_dir_sep(.back()).
also changed behavior to reflect the fact that "" is the VFS root
_directory_
- Path::Join now allows 2 identical path types (e.g. VfsPath) or one
char* literal (prevents inadvertently introducing non-safe characters).
to convert from wstring or wchar_t, use an explicit ctor (e.g.
VfsPath(wchar_t_string))

This was SVN commit r9091.
This commit is contained in:
janwas 2011-03-21 19:54:08 +00:00
parent 6d25329412
commit c3405e6f50
57 changed files with 179 additions and 165 deletions

View File

@ -248,7 +248,7 @@ VfsPath CColladaManager::GetLoadableFilename(const VfsPath& pathnameNoExtension,
const wchar_t* realDaePath = wcsstr(realDaeBuf, L"mods/"); const wchar_t* realDaePath = wcsstr(realDaeBuf, L"mods/");
// cachedPmdVfsPath is "cache/mods/whatever/art/meshes/whatever_{hash}.pmd" // cachedPmdVfsPath is "cache/mods/whatever/art/meshes/whatever_{hash}.pmd"
VfsPath cachedPmdVfsPath = Path::Join(L"cache/", realDaePath); VfsPath cachedPmdVfsPath = Path::Join("cache", VfsPath(realDaePath));
cachedPmdVfsPath = Path::ChangeExtension(cachedPmdVfsPath, extension); cachedPmdVfsPath = Path::ChangeExtension(cachedPmdVfsPath, extension);
// If it's not in the cache, we'll have to create it first // If it's not in the cache, we'll have to create it first

View File

@ -142,11 +142,11 @@ bool CObjectBase::Load(const VfsPath& pathname)
if (option_name == el_mesh) if (option_name == el_mesh)
{ {
currentVariant->m_ModelFilename = Path::Join(L"art/meshes", option.GetText().FromUTF8()); currentVariant->m_ModelFilename = Path::Join("art/meshes", option.GetText().FromUTF8());
} }
else if (option_name == el_texture) else if (option_name == el_texture)
{ {
currentVariant->m_TextureFilename = Path::Join(L"art/textures/skins", option.GetText().FromUTF8()); currentVariant->m_TextureFilename = Path::Join("art/textures/skins", option.GetText().FromUTF8());
} }
else if (option_name == el_decal) else if (option_name == el_decal)
{ {
@ -178,7 +178,7 @@ bool CObjectBase::Load(const VfsPath& pathname)
} }
else if (ae.Name == at_file) else if (ae.Name == at_file)
{ {
anim.m_FileName = Path::Join(L"art/animation", ae.Value.FromUTF8()); anim.m_FileName = Path::Join("art/animation", ae.Value.FromUTF8());
} }
else if (ae.Name == at_speed) else if (ae.Name == at_speed)
{ {
@ -239,7 +239,7 @@ bool CObjectBase::Load(const VfsPath& pathname)
} }
else if (child_name == el_material) else if (child_name == el_material)
{ {
m_Material = Path::Join(L"art/materials", child.GetText().FromUTF8()); m_Material = Path::Join("art/materials", child.GetText().FromUTF8());
} }
} }

View File

@ -85,7 +85,7 @@ CObjectBase* CObjectManager::FindObjectBase(const CStrW& objectname)
CObjectBase* obj = new CObjectBase(*this); CObjectBase* obj = new CObjectBase(*this);
VfsPath pathname = Path::Join(L"art/actors/", objectname); VfsPath pathname = Path::Join("art/actors/", objectname);
if (obj->Load(pathname)) if (obj->Load(pathname))
{ {

View File

@ -168,7 +168,7 @@ void CTerrainTextureManager::RecurseDirectory(const CTerrainPropertiesPtr& paren
CTerrainPropertiesPtr props; CTerrainPropertiesPtr props;
// Load terrains.xml first, if it exists // Load terrains.xml first, if it exists
VfsPath pathname = Path::Join(path, L"terrains.xml"); VfsPath pathname = Path::Join(path, "terrains.xml");
if (VfsFileExists(pathname)) if (VfsFileExists(pathname))
props = GetPropertiesFromFile(parentProps, pathname); props = GetPropertiesFromFile(parentProps, pathname);

View File

@ -302,7 +302,7 @@ public:
CTexturePtr texture = CreateTexture(textureProps); CTexturePtr texture = CreateTexture(textureProps);
CTextureConverter::Settings settings = GetConverterSettings(texture); CTextureConverter::Settings settings = GetConverterSettings(texture);
if (!m_TextureConverter.ConvertTexture(texture, sourcePath, Path::Join(L"cache", archiveCachePath), settings)) if (!m_TextureConverter.ConvertTexture(texture, sourcePath, Path::Join("cache", archiveCachePath), settings))
return false; return false;
while (true) while (true)
@ -409,7 +409,7 @@ public:
VfsPath p; VfsPath p;
for (fs::wpath::iterator it = srcPath.begin(); it != srcPath.end(); ++it) for (fs::wpath::iterator it = srcPath.begin(); it != srcPath.end(); ++it)
{ {
VfsPath settingsPath = Path::Join(p, L"textures.xml"); VfsPath settingsPath = Path::Join(p, "textures.xml");
m_HotloadFiles[settingsPath].insert(texture); m_HotloadFiles[settingsPath].insert(texture);
CTextureConverter::SettingsFile* f = GetSettingsFile(settingsPath); CTextureConverter::SettingsFile* f = GetSettingsFile(settingsPath);
if (f) if (f)

View File

@ -27,8 +27,8 @@
#include "ps/CLogger.h" #include "ps/CLogger.h"
#include "ps/XML/RelaxNG.h" #include "ps/XML/RelaxNG.h"
static NativePath MOD_PATH(Path::Join(DataDir(), L"mods/_test.mesh")); static NativePath MOD_PATH(Path::Join(DataDir(), "mods/_test.mesh"));
static NativePath CACHE_PATH(Path::Join(DataDir(), L"_testcache")); static NativePath CACHE_PATH(Path::Join(DataDir(), "_testcache"));
const wchar_t* srcDAE = L"collada/sphere.dae"; const wchar_t* srcDAE = L"collada/sphere.dae";
const wchar_t* srcPMD = L"collada/sphere.pmd"; const wchar_t* srcPMD = L"collada/sphere.pmd";
@ -59,7 +59,7 @@ class TestMeshManager : public CxxTest::TestSuite
g_VFS = CreateVfs(20*MiB); g_VFS = CreateVfs(20*MiB);
TS_ASSERT_OK(g_VFS->Mount(L"", MOD_PATH)); TS_ASSERT_OK(g_VFS->Mount(L"", MOD_PATH));
TS_ASSERT_OK(g_VFS->Mount(L"collada/", Path::Join(DataDir(), L"tests/collada"), VFS_MOUNT_MUST_EXIST)); TS_ASSERT_OK(g_VFS->Mount(L"collada/", Path::Join(DataDir(), "tests/collada"), VFS_MOUNT_MUST_EXIST));
// Mount _testcache onto virtual /cache - don't use the normal cache // Mount _testcache onto virtual /cache - don't use the normal cache
// directory because that's full of loads of cached files from the // directory because that's full of loads of cached files from the

View File

@ -32,11 +32,11 @@ public:
void setUp() void setUp()
{ {
DeleteDirectory(Path::Join(DataDir(), L"_testcache")); // clean up in case the last test run failed DeleteDirectory(Path::Join(DataDir(), "_testcache")); // clean up in case the last test run failed
m_VFS = CreateVfs(20*MiB); m_VFS = CreateVfs(20*MiB);
TS_ASSERT_OK(m_VFS->Mount(L"", Path::Join(DataDir(), L"mods/_test.tex"), VFS_MOUNT_MUST_EXIST)); TS_ASSERT_OK(m_VFS->Mount(L"", Path::Join(DataDir(), "mods/_test.tex"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(m_VFS->Mount(L"cache/", Path::Join(DataDir(), L"_testcache"))); TS_ASSERT_OK(m_VFS->Mount(L"cache/", Path::Join(DataDir(), "_testcache")));
tex_codec_register_all(); tex_codec_register_all();
} }
@ -46,7 +46,7 @@ public:
tex_codec_unregister_all(); tex_codec_unregister_all();
m_VFS.reset(); m_VFS.reset();
DeleteDirectory(Path::Join(DataDir(), L"_testcache")); DeleteDirectory(Path::Join(DataDir(), "_testcache"));
} }
void test_convert_quality() void test_convert_quality()

View File

@ -34,11 +34,11 @@ public:
void setUp() void setUp()
{ {
DeleteDirectory(Path::Join(DataDir(), L"_testcache")); // clean up in case the last test run failed DeleteDirectory(Path::Join(DataDir(), "_testcache")); // clean up in case the last test run failed
m_VFS = CreateVfs(20*MiB); m_VFS = CreateVfs(20*MiB);
TS_ASSERT_OK(m_VFS->Mount(L"", Path::Join(DataDir(), L"mods/_test.tex"), VFS_MOUNT_MUST_EXIST)); TS_ASSERT_OK(m_VFS->Mount(L"", Path::Join(DataDir(), "mods/_test.tex"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(m_VFS->Mount(L"cache/", Path::Join(DataDir(), L"_testcache"))); TS_ASSERT_OK(m_VFS->Mount(L"cache/", Path::Join(DataDir(), "_testcache")));
h_mgr_init(); h_mgr_init();
tex_codec_register_all(); tex_codec_register_all();
@ -54,7 +54,7 @@ public:
h_mgr_shutdown(); h_mgr_shutdown();
m_VFS.reset(); m_VFS.reset();
DeleteDirectory(Path::Join(DataDir(), L"_testcache")); DeleteDirectory(Path::Join(DataDir(), "_testcache"));
} }
void test_load_basic() void test_load_basic()

View File

@ -1578,7 +1578,7 @@ void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite
if (attr_name == "texture") if (attr_name == "texture")
{ {
image.m_TextureName = Path::Join(L"art/textures/ui", attr_value); image.m_TextureName = Path::Join("art/textures/ui", attr_value);
} }
else else
if (attr_name == "size") if (attr_name == "size")

View File

@ -115,7 +115,7 @@ void CGUIManager::LoadPage(SGUIPage& page)
page.gui.reset(new CGUI()); page.gui.reset(new CGUI());
page.gui->Initialize(); page.gui->Initialize();
VfsPath path = Path::Join(L"gui", page.name.c_str()); VfsPath path = Path::Join("gui", VfsPath(page.name.c_str()));
page.inputs.insert(path); page.inputs.insert(path);
CXeromyces xero; CXeromyces xero;
@ -144,7 +144,7 @@ void CGUIManager::LoadPage(SGUIPage& page)
CStrW name (node.GetText().FromUTF8()); CStrW name (node.GetText().FromUTF8());
TIMER(name.c_str()); TIMER(name.c_str());
VfsPath path = Path::Join(L"gui", name.c_str()); VfsPath path = Path::Join("gui", VfsPath(name.c_str()));
page.gui->LoadXmlFile(path, page.inputs); page.gui->LoadXmlFile(path, page.inputs);
} }

View File

@ -384,7 +384,7 @@ void GUIRenderer::UpdateDrawCallCache(DrawCalls &Calls, const CStr& SpriteName,
// TODO: Should check (nicely) that this is a valid file? // TODO: Should check (nicely) that this is a valid file?
SGUIImage Image; SGUIImage Image;
Image.m_TextureName = Path::Join(L"art/textures/ui", wstring_from_utf8(SpriteName.substr(10))); Image.m_TextureName = Path::Join("art/textures/ui", NativePathFromString(SpriteName.substr(10)));
CClientArea ca(CRect(0, 0, 0, 0), CRect(0, 0, 100, 100)); CClientArea ca(CRect(0, 0, 0, 0), CRect(0, 0, 100, 100));
Image.m_Size = ca; Image.m_Size = ca;

View File

@ -433,7 +433,7 @@ void ForceGC(void* cbdata)
void DumpSimState(void* UNUSED(cbdata)) void DumpSimState(void* UNUSED(cbdata))
{ {
NativePath path = Path::Join(psLogDir(), L"sim_dump.txt"); NativePath path = Path::Join(psLogDir(), "sim_dump.txt");
std::ofstream file (StringFromNativePath(path).c_str(), std::ofstream::out | std::ofstream::trunc); std::ofstream file (StringFromNativePath(path).c_str(), std::ofstream::out | std::ofstream::trunc);
g_Game->GetSimulation2()->DumpDebugState(file); g_Game->GetSimulation2()->DumpDebugState(file);
} }

View File

@ -174,7 +174,7 @@ LibError debug_WriteCrashlog(const wchar_t* text)
return ERR::REENTERED; // NOWARN return ERR::REENTERED; // NOWARN
FILE* f; FILE* f;
NativePath pathname = Path::Join(ah_get_log_dir(), L"crashlog.txt"); NativePath pathname = Path::Join(ah_get_log_dir(), "crashlog.txt");
errno_t err = _wfopen_s(&f, pathname.c_str(), L"w"); errno_t err = _wfopen_s(&f, pathname.c_str(), L"w");
if(err != 0) if(err != 0)
{ {

View File

@ -43,7 +43,7 @@ void dbghelp_ImportFunctions()
// application loaded.") and then the system directory, whose // application loaded.") and then the system directory, whose
// dbghelp.dll is too old. we therefore specify the full path // dbghelp.dll is too old. we therefore specify the full path
// to our executable directory, which contains a newer dbghelp.dll. // to our executable directory, which contains a newer dbghelp.dll.
const NativePath pathname = Path::Join(wutil_DetectExecutablePath(), L"dbghelp.dll"); const NativePath pathname = Path::Join(wutil_DetectExecutablePath(), "dbghelp.dll");
HMODULE hDbghelp = LoadLibraryW(pathname.c_str()); HMODULE hDbghelp = LoadLibraryW(pathname.c_str());
debug_assert(hDbghelp); debug_assert(hDbghelp);
#define FUNC(ret, name, params) p##name = (ret (__stdcall*) params)GetProcAddress(hDbghelp, #name); #define FUNC(ret, name, params) p##name = (ret (__stdcall*) params)GetProcAddress(hDbghelp, #name);

View File

@ -30,9 +30,9 @@
#include <time.h> #include <time.h>
#include <limits> #include <limits>
#include "lib/utf8.h"
#include "lib/bits.h" #include "lib/bits.h"
#include "lib/byte_order.h" #include "lib/byte_order.h"
#include "lib/utf8.h" // wstring_from_utf8
#include "lib/fat_time.h" #include "lib/fat_time.h"
#include "lib/path_util.h" #include "lib/path_util.h"
#include "lib/allocators/pool.h" #include "lib/allocators/pool.h"
@ -412,7 +412,7 @@ public:
WARN_RETURN(ERR::CORRUPTED); WARN_RETURN(ERR::CORRUPTED);
const VfsPath relativePathname(cdfh->Pathname()); const VfsPath relativePathname(cdfh->Pathname());
if(relativePathname.empty() || !path_is_dir_sep(relativePathname[relativePathname.length()-1])) // ignore directories if(!Path::IsDirectory(relativePathname))
{ {
const NativePath name = Path::Filename(relativePathname); const NativePath name = Path::Filename(relativePathname);
FileInfo fileInfo(name, cdfh->USize(), cdfh->MTime()); FileInfo fileInfo(name, cdfh->USize(), cdfh->MTime());

View File

@ -28,7 +28,6 @@
#include <string> #include <string>
#include "lib/path_util.h" #include "lib/path_util.h"
#include "lib/utf8.h" // wstring_from_utf8
#include "lib/posix/posix_filesystem.h" #include "lib/posix/posix_filesystem.h"
@ -122,7 +121,7 @@ LibError CreateDirectories(const NativePath& path, mode_t mode)
// If we were passed a path ending with '/', strip the '/' now so that // If we were passed a path ending with '/', strip the '/' now so that
// we can consistently use Path to find parent directory names // we can consistently use Path to find parent directory names
if(path_is_dir_sep(path[path.length()-1])) if(Path::IsDirectory(path))
return CreateDirectories(Path::Path(path), mode); return CreateDirectories(Path::Path(path), mode);
RETURN_ERR(CreateDirectories(Path::Path(path), mode)); RETURN_ERR(CreateDirectories(Path::Path(path), mode));

View File

@ -38,21 +38,13 @@ ERROR_ASSOCIATE(ERR::PATH_COMPONENT_SEPARATOR, L"path component contains dir sep
ERROR_ASSOCIATE(ERR::PATH_NOT_FOUND, L"path not found", -1); ERROR_ASSOCIATE(ERR::PATH_NOT_FOUND, L"path not found", -1);
bool path_is_dir_sep(wchar_t c) static bool path_is_dir_sep(wchar_t c)
{ {
// note: ideally path strings would only contain '/' or even SYS_DIR_SEP.
// however, windows-specific code (e.g. the sound driver detection)
// uses these routines with '\\' strings. converting them all to
// '/' and then back before passing to WinAPI would be annoying.
// also, the self-tests verify correct operation of such strings.
// it would be error-prone to only test the platform's separator
// strings there. hence, we allow all separators here.
if(c == '/' || c == '\\') if(c == '/' || c == '\\')
return true; return true;
return false; return false;
} }
// is s2 a subpath of s1, or vice versa? // is s2 a subpath of s1, or vice versa?
// (equal counts as subpath) // (equal counts as subpath)
bool path_is_subpath(const wchar_t* s1, const wchar_t* s2) bool path_is_subpath(const wchar_t* s1, const wchar_t* s2)

View File

@ -54,14 +54,6 @@ namespace ERR
**/ **/
LIB_API LibError path_component_validate(const wchar_t* name); LIB_API LibError path_component_validate(const wchar_t* name);
/**
* is the given character a path separator character?
*
* @param c character to test
* @return bool
**/
LIB_API bool path_is_dir_sep(wchar_t c);
/** /**
* is s2 a subpath of s1, or vice versa? (equal counts as subpath) * is s2 a subpath of s1, or vice versa? (equal counts as subpath)
* *
@ -79,72 +71,106 @@ LIB_API bool path_is_subpath(const wchar_t* s1, const wchar_t* s2);
**/ **/
LIB_API const wchar_t* path_name_only(const wchar_t* path); LIB_API const wchar_t* path_name_only(const wchar_t* path);
namespace Path { namespace Path {
static inline NativePath Path(const NativePath& pathname) template<class Path_t>
static inline bool IsDirectory(const Path_t& pathname)
{
if(pathname.empty()) // (ensure back() is safe)
return false; // (the VFS root directory is represented as an empty string)
// note: ideally, path strings would only contain '/' or even SYS_DIR_SEP.
// however, windows-specific code (e.g. the sound driver detection)
// uses these routines with '\\' strings. converting them all to
// '/' and then back before passing to OS functions would be annoying.
// also, the self-tests verify correct operation of such strings.
// it would be error-prone to only test the platform's separator
// strings there. hence, we allow all separators here.
return pathname.back() == '/' || pathname.back() == '\\';
}
template<class Path_t>
static inline Path_t Path(const Path_t& pathname)
{ {
size_t n = pathname.find_last_of('/'); size_t n = pathname.find_last_of('/');
if(n == NativePath::npos) if(n == Path_t::npos)
{ {
n = pathname.find_last_of('\\'); n = pathname.find_last_of('\\');
if(n == NativePath::npos) if(n == Path_t::npos)
return L""; return L"";
} }
return pathname.substr(0, n); return pathname.substr(0, n);
} }
static inline NativePath Filename(const NativePath& pathname) template<class Path_t>
static inline Path_t Filename(const Path_t& pathname)
{ {
size_t n = pathname.find_last_of('/'); size_t n = pathname.find_last_of('/');
if(n == NativePath::npos) if(n == Path_t::npos)
{ {
n = pathname.find_last_of('\\'); n = pathname.find_last_of('\\');
if(n == NativePath::npos) if(n == Path_t::npos)
return pathname; return pathname;
} }
return pathname.substr(n+1); return pathname.substr(n+1);
} }
static inline NativePath Basename(const NativePath& pathname) template<class Path_t>
static inline Path_t Basename(const Path_t& pathname)
{ {
const NativePath filename = Filename(pathname); const Path_t filename = Filename(pathname);
const size_t idxDot = filename.find_last_of('.'); const size_t idxDot = filename.find_last_of('.');
if(idxDot == NativePath::npos) if(idxDot == Path_t::npos)
return filename; return filename;
return filename.substr(0, idxDot); return filename.substr(0, idxDot);
} }
static inline NativePath Extension(const NativePath& pathname) template<class Path_t>
static inline std::wstring Extension(const Path_t& pathname)
{ {
const size_t idxDot = pathname.find_last_of('.'); const size_t idxDot = pathname.find_last_of('.');
if(idxDot == NativePath::npos) if(idxDot == Path_t::npos)
return NativePath(); return Path_t();
return pathname.substr(idxDot); return pathname.substr(idxDot);
} }
static inline NativePath Join(const NativePath& path1, const NativePath& path2) static inline std::wstring JoinPathStrings(const std::wstring& path1, const std::wstring& path2)
{ {
NativePath ret = path1; std::wstring ret = path1;
if(!path1.empty() && path1[path1.length()-1] != '/' && path1[path1.length()-1] != '\\') if(!IsDirectory(path1))
ret += '/'; ret += '/';
ret += path2; ret += path2;
return ret; return ret;
} }
static inline NativePath Join(const NativePath& path1, const NativePath& path2, const NativePath& path3) template<class Path_t>
static inline Path_t Join(const Path_t& path1, const Path_t& path2)
{ {
return Join(Join(path1, path2), path3); return JoinPathStrings(path1, path2);
} }
static inline NativePath AddSlash(const NativePath& path) template<class Path_t>
static inline Path_t Join(const Path_t& path1, const char* literal)
{ {
return (!path.empty() && path_is_dir_sep(path[path.length()-1]))? path : path+L'/'; return JoinPathStrings(path1, NativePathFromString(literal));
} }
static inline NativePath ChangeExtension(const NativePath& pathname, const NativePath& extension) template<class Path_t>
static inline Path_t Join(const char* literal, const Path_t& path2)
{ {
return Join(Path(pathname), Basename(Filename(pathname))+extension); return JoinPathStrings(NativePathFromString(literal), path2);
}
template<class Path_t>
static inline Path_t AddSlash(const Path_t& path)
{
return IsDirectory(path)? path : path+L'/';
}
template<class Path_t>
static inline Path_t ChangeExtension(const Path_t& pathname, const std::wstring& extension)
{
return Join(Path(pathname), Basename(pathname)+extension);
} }
} // namespace Path } // namespace Path

View File

@ -237,7 +237,7 @@ LibError dir_watch_Poll(DirWatchNotifications& notifications)
continue; continue;
} }
DirWatch* dirWatch = (DirWatch*)polled_notifications[i].userdata; DirWatch* dirWatch = (DirWatch*)polled_notifications[i].userdata;
NativePath pathname = Path::Join(dirWatch->path, NativePathFromString(polled_notifications[i].filename)); NativePath pathname = Path::Join(dirWatch->path, polled_notifications[i].filename);
notifications.push_back(DirWatchNotification(pathname, type)); notifications.push_back(DirWatchNotification(pathname, type));
} }

View File

@ -31,7 +31,7 @@
#include <cstdio> #include <cstdio>
LibError sys_get_executable_name(std::wstring& pathname) LibError sys_get_executable_name(NativePath& pathname)
{ {
const char* path; const char* path;
Dl_info dl_info; Dl_info dl_info;
@ -53,7 +53,7 @@ LibError sys_get_executable_name(std::wstring& pathname)
char* resolved = realpath(path, resolvedBuf); char* resolved = realpath(path, resolvedBuf);
if (!resolved) if (!resolved)
return ERR::FAIL; return ERR::FAIL;
pathname = wstring_from_utf8(resolved); pathname = NativePathFromString(resolved);
return INFO::OK; return INFO::OK;
} }
@ -72,7 +72,7 @@ LibError sys_get_executable_name(std::wstring& pathname)
char* resolved = realpath(absolute, resolvedBuf); char* resolved = realpath(absolute, resolvedBuf);
if (!resolved) if (!resolved)
return ERR::NO_SYS; return ERR::NO_SYS;
pathname = wstring_from_utf8(resolved); pathname = NativePathFromString(resolved);
return INFO::OK; return INFO::OK;
} }

View File

@ -78,7 +78,7 @@ LibError gfx_get_video_mode(int* xres, int* yres, int* bpp, int* freq)
} }
LibError sys_get_executable_name(std::wstring& pathname) LibError sys_get_executable_name(NativePath& pathname)
{ {
static char name[PATH_MAX]; static char name[PATH_MAX];
static bool init = false; static bool init = false;
@ -102,7 +102,7 @@ LibError sys_get_executable_name(std::wstring& pathname)
debug_printf(L"app bundle name: %hs\n", name); debug_printf(L"app bundle name: %hs\n", name);
} }
pathname = wstring_from_utf8(name); pathname = NativePathFromString(name);
return INFO::OK; return INFO::OK;
} }

View File

@ -57,7 +57,7 @@ struct wdirent* wreaddir(WDIR* wd)
dirent* ent = readdir(wd->d); dirent* ent = readdir(wd->d);
if(!ent) if(!ent)
return 0; return 0;
std::wstring name = wstring_from_utf8(ent->d_name); NativePath name = NativePathFromString(ent->d_name);
wcscpy_s(wd->name, ARRAY_SIZE(wd->name), name.c_str()); wcscpy_s(wd->name, ARRAY_SIZE(wd->name), name.c_str());
return &wd->ent; return &wd->ent;
} }

View File

@ -333,7 +333,7 @@ static NativePath DriverPathname()
#endif #endif
char filename[PATH_MAX]; char filename[PATH_MAX];
sprintf_s(filename, ARRAY_SIZE(filename), "aken%s%s.sys", bits, debug); sprintf_s(filename, ARRAY_SIZE(filename), "aken%s%s.sys", bits, debug);
return Path::Join(wutil_ExecutablePath(), NativePathFromString(filename)); return Path::Join(wutil_ExecutablePath(), filename);
} }

View File

@ -1871,7 +1871,7 @@ void wdbg_sym_WriteMinidump(EXCEPTION_POINTERS* exception_pointers)
WinScopedLock lock(WDBG_SYM_CS); WinScopedLock lock(WDBG_SYM_CS);
NativePath path = Path::Join(ah_get_log_dir(), L"crashlog.dmp"); NativePath path = Path::Join(ah_get_log_dir(), "crashlog.dmp");
HANDLE hFile = CreateFileW(path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0); HANDLE hFile = CreateFileW(path.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0);
if(hFile == INVALID_HANDLE_VALUE) if(hFile == INVALID_HANDLE_VALUE)
{ {

View File

@ -370,7 +370,7 @@ class DirWatchManager
public: public:
LibError Add(const NativePath& path, PDirWatch& dirWatch) LibError Add(const NativePath& path, PDirWatch& dirWatch)
{ {
debug_assert(path_is_dir_sep(path.back())); // must be a directory path debug_assert(Path::IsDirectory(path));
// check if this is a subdirectory of a tree that's already being // check if this is a subdirectory of a tree that's already being
// watched (this is much faster than issuing a new watch; it also // watched (this is much faster than issuing a new watch; it also

View File

@ -57,7 +57,7 @@ void* dlopen(const char* so_name, int flags)
{ {
debug_assert(!(flags & RTLD_GLOBAL)); debug_assert(!(flags & RTLD_GLOBAL));
NativePath pathname = Path::ChangeExtension(wstring_from_utf8(so_name), L".dll"); NativePath pathname = Path::ChangeExtension(NativePathFromString(so_name), L".dll");
HMODULE hModule = LoadLibraryW(pathname.c_str()); HMODULE hModule = LoadLibraryW(pathname.c_str());
return void_from_HMODULE(hModule); return void_from_HMODULE(hModule);
} }

View File

@ -1485,14 +1485,11 @@ static NativePath GetStdoutPathname()
wchar_t pathnameEXE[MAX_PATH]; wchar_t pathnameEXE[MAX_PATH];
const DWORD charsWritten = GetModuleFileNameW(0, pathnameEXE, ARRAY_SIZE(pathnameEXE)); const DWORD charsWritten = GetModuleFileNameW(0, pathnameEXE, ARRAY_SIZE(pathnameEXE));
debug_assert(charsWritten); debug_assert(charsWritten);
const NativePath path = Path::Path(pathnameEXE);
// add the EXE name to the filename to allow multiple executables // add the EXE name to the filename to allow multiple executables
// with their own redirections. (we can't use wutil_ExecutablePath // with their own redirections. (we can't use wutil_ExecutablePath
// because it doesn't return the basename) // because it doesn't return the basename)
NativePath name = Path::Basename(pathnameEXE); NativePath pathname = Path::ChangeExtension(NativePath(pathnameEXE), L"_stdout.txt");
NativePath pathname = Path::Join(path, (name+L"_stdout.txt"));
return pathname; return pathname;
} }

View File

@ -99,7 +99,7 @@ static BOOL CALLBACK DirectSoundCallback(void* guid, const wchar_t* UNUSED(descr
// note: $system\\drivers is not in LoadLibrary's search list, // note: $system\\drivers is not in LoadLibrary's search list,
// so we have to give the full pathname. // so we have to give the full pathname.
directSoundDriverPath = Path::Join(wutil_SystemPath(), L"drivers", module); directSoundDriverPath = Path::Join(Path::Join(wutil_SystemPath(), "drivers"), NativePath(module));
// we assume the first "driver name" (sound card) is the one we want; // we assume the first "driver name" (sound card) is the one we want;
// stick with that and stop calling. // stick with that and stop calling.

View File

@ -272,7 +272,7 @@ NativePath wutil_DetectExecutablePath()
wchar_t modulePathname[MAX_PATH+1] = {0}; wchar_t modulePathname[MAX_PATH+1] = {0};
const DWORD len = GetModuleFileNameW(GetModuleHandle(0), modulePathname, MAX_PATH); const DWORD len = GetModuleFileNameW(GetModuleHandle(0), modulePathname, MAX_PATH);
debug_assert(len != 0); debug_assert(len != 0);
return Path::Path(modulePathname); return Path::Path(NativePath(modulePathname));
} }
// (NB: wutil_Init is called before static ctors => use placement new) // (NB: wutil_Init is called before static ctors => use placement new)

View File

@ -438,7 +438,7 @@ static void RunGameOrAtlas(int argc, const char* argv[])
Paths paths(args); Paths paths(args);
g_VFS = CreateVfs(20 * MiB); g_VFS = CreateVfs(20 * MiB);
g_VFS->Mount(L"cache/", paths.Cache(), VFS_MOUNT_ARCHIVABLE); g_VFS->Mount(L"cache/", paths.Cache(), VFS_MOUNT_ARCHIVABLE);
g_VFS->Mount(L"", Path::Join(paths.RData(), L"mods/public"), VFS_MOUNT_MUST_EXIST); g_VFS->Mount(L"", Path::Join(paths.RData(), "mods/public"), VFS_MOUNT_MUST_EXIST);
{ {
CReplayPlayer replay; CReplayPlayer replay;

View File

@ -182,7 +182,7 @@ void CNetTurnManager::OnSyncError(u32 turn, const std::string& expectedHash)
bool ok = m_Simulation2.ComputeStateHash(hash, quick); bool ok = m_Simulation2.ComputeStateHash(hash, quick);
debug_assert(ok); debug_assert(ok);
NativePath path = Path::Join(psLogDir(), L"oos_dump.txt"); NativePath path = Path::Join(psLogDir(), "oos_dump.txt");
std::ofstream file (StringFromNativePath(path).c_str(), std::ofstream::out | std::ofstream::trunc); std::ofstream file (StringFromNativePath(path).c_str(), std::ofstream::out | std::ofstream::trunc);
m_Simulation2.DumpDebugState(file); m_Simulation2.DumpDebugState(file);
file.close(); file.close();

View File

@ -38,8 +38,8 @@ public:
void setUp() void setUp()
{ {
g_VFS = CreateVfs(20 * MiB); g_VFS = CreateVfs(20 * MiB);
TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), L"mods/public"), VFS_MOUNT_MUST_EXIST)); TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), "mods/public"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"cache", Path::Join(DataDir(), L"_testcache"))); TS_ASSERT_OK(g_VFS->Mount(L"cache", Path::Join(DataDir(), "_testcache")));
CXeromyces::Startup(); CXeromyces::Startup();
// Need some stuff for terrain movement costs: // Need some stuff for terrain movement costs:
@ -60,7 +60,7 @@ public:
CXeromyces::Terminate(); CXeromyces::Terminate();
g_VFS.reset(); g_VFS.reset();
DeleteDirectory(Path::Join(DataDir(), L"_testcache")); DeleteDirectory(Path::Join(DataDir(), "_testcache"));
} }
bool clients_are_all(const std::vector<CNetClient*>& clients, uint state) bool clients_are_all(const std::vector<CNetClient*>& clients, uint state)

View File

@ -39,9 +39,9 @@ CArchiveBuilder::CArchiveBuilder(const std::wstring& mod, const std::wstring& te
m_VFS = CreateVfs(20*MiB); m_VFS = CreateVfs(20*MiB);
DeleteDirectory(Path::Join(m_TempDir, L"_archivecache")); // clean up in case the last run failed DeleteDirectory(Path::Join(m_TempDir, "_archivecache")); // clean up in case the last run failed
m_VFS->Mount(L"cache/", Path::Join(m_TempDir, L"_archivecache/")); m_VFS->Mount(L"cache/", Path::Join(m_TempDir, "_archivecache/"));
m_VFS->Mount(L"", Path::AddSlash(mod), VFS_MOUNT_MUST_EXIST); m_VFS->Mount(L"", Path::AddSlash(mod), VFS_MOUNT_MUST_EXIST);
@ -53,7 +53,7 @@ CArchiveBuilder::~CArchiveBuilder()
{ {
m_VFS.reset(); m_VFS.reset();
DeleteDirectory(Path::Join(m_TempDir, L"_archivecache")); DeleteDirectory(Path::Join(m_TempDir, "_archivecache"));
tex_codec_unregister_all(); tex_codec_unregister_all();
} }
@ -102,7 +102,7 @@ void CArchiveBuilder::Build(const std::wstring& archive)
debug_assert(ok); debug_assert(ok);
std::wstring cachedRealPath; std::wstring cachedRealPath;
ret = m_VFS->GetRealPath(Path::Join(L"cache", cachedPath), cachedRealPath); ret = m_VFS->GetRealPath(Path::Join("cache", cachedPath), cachedRealPath);
debug_assert(ret == INFO::OK); debug_assert(ret == INFO::OK);
writer->AddFile(cachedRealPath, cachedPath); writer->AddFile(cachedRealPath, cachedPath);
@ -126,7 +126,7 @@ void CArchiveBuilder::Build(const std::wstring& archive)
debug_assert(ok); debug_assert(ok);
std::wstring cachedRealPath; std::wstring cachedRealPath;
ret = m_VFS->GetRealPath(Path::Join(L"cache", cachedPath), cachedRealPath); ret = m_VFS->GetRealPath(Path::Join("cache", cachedPath), cachedRealPath);
debug_assert(ret == INFO::OK); debug_assert(ret == INFO::OK);
writer->AddFile(cachedRealPath, cachedPath); writer->AddFile(cachedRealPath, cachedPath);

View File

@ -75,10 +75,10 @@ const char* html_header1 = "</h2>\n";
CLogger::CLogger() CLogger::CLogger()
{ {
std::wstring mainlogPath(Path::Join(psLogDir(), L"mainlog.html")); NativePath mainlogPath(Path::Join(psLogDir(), "mainlog.html"));
m_MainLog = new std::ofstream(utf8_from_wstring(mainlogPath).c_str(), std::ofstream::out | std::ofstream::trunc); m_MainLog = new std::ofstream(utf8_from_wstring(mainlogPath).c_str(), std::ofstream::out | std::ofstream::trunc);
std::wstring interestinglogPath(Path::Join(psLogDir(), L"interestinglog.html")); NativePath interestinglogPath(Path::Join(psLogDir(), "interestinglog.html"));
m_InterestingLog = new std::ofstream(utf8_from_wstring(interestinglogPath).c_str(), std::ofstream::out | std::ofstream::trunc); m_InterestingLog = new std::ofstream(utf8_from_wstring(interestinglogPath).c_str(), std::ofstream::out | std::ofstream::trunc);
m_OwnsStreams = true; m_OwnsStreams = true;

View File

@ -109,10 +109,7 @@ bool CCacheLoader::CanUseArchiveCache(const VfsPath& sourcePath, const VfsPath&
VfsPath CCacheLoader::ArchiveCachePath(const VfsPath& sourcePath) VfsPath CCacheLoader::ArchiveCachePath(const VfsPath& sourcePath)
{ {
VfsPath sourceDir = Path::Path(sourcePath); return Path::ChangeExtension(sourcePath, Path::Extension(sourcePath) + L".cached" + m_FileExtension);
std::wstring sourceName = Path::Filename(sourcePath);
return Path::Join(sourceDir, sourceName + L".cached" + m_FileExtension);
} }
VfsPath CCacheLoader::LooseCachePath(const VfsPath& sourcePath, const MD5& initialHash, u32 version) VfsPath CCacheLoader::LooseCachePath(const VfsPath& sourcePath, const MD5& initialHash, u32 version)
@ -145,9 +142,7 @@ VfsPath CCacheLoader::LooseCachePath(const VfsPath& sourcePath, const MD5& initi
digestPrefix << std::setfill(L'0') << std::setw(2) << (int)digest[i]; digestPrefix << std::setfill(L'0') << std::setw(2) << (int)digest[i];
// Construct the final path // Construct the final path
VfsPath sourceDir = Path::Path(sourcePath); return Path::Join("cache", Path::ChangeExtension(sourcePath, std::wstring(L".") + digestPrefix.str() + m_FileExtension));
std::wstring sourceName = Path::Filename(sourcePath);
return Path::Join(L"cache", sourceDir, sourceName + L"." + digestPrefix.str() + m_FileExtension);
// TODO: we should probably include the mod name, once that's possible (http://trac.wildfiregames.com/ticket/564) // TODO: we should probably include the mod name, once that's possible (http://trac.wildfiregames.com/ticket/564)
} }

View File

@ -454,8 +454,8 @@ static void InitVfs(const CmdLineArgs& args)
const size_t cacheSize = ChooseCacheSize(); const size_t cacheSize = ChooseCacheSize();
g_VFS = CreateVfs(cacheSize); g_VFS = CreateVfs(cacheSize);
g_VFS->Mount(L"screenshots/", Path::Join(paths.Data(), L"screenshots/")); g_VFS->Mount(L"screenshots/", Path::Join(paths.Data(), "screenshots/"));
const NativePath readonlyConfig = Path::Join(paths.RData(), L"config/"); const NativePath readonlyConfig = Path::Join(paths.RData(), "config/");
g_VFS->Mount(L"config/", readonlyConfig); g_VFS->Mount(L"config/", readonlyConfig);
if(readonlyConfig != paths.Config()) if(readonlyConfig != paths.Config())
g_VFS->Mount(L"config/", paths.Config()); g_VFS->Mount(L"config/", paths.Config());
@ -466,8 +466,8 @@ static void InitVfs(const CmdLineArgs& args)
if(!args.Has("onlyPublicFiles")) if(!args.Has("onlyPublicFiles"))
mods.push_back("internal"); mods.push_back("internal");
NativePath modArchivePath = Path::Join(paths.Cache(), L"mods"); NativePath modArchivePath = Path::Join(paths.Cache(), "mods");
NativePath modLoosePath = Path::Join(paths.RData(), L"mods"); NativePath modLoosePath = Path::Join(paths.RData(), "mods");
for (size_t i = 0; i < mods.size(); ++i) for (size_t i = 0; i < mods.size(); ++i)
{ {
size_t priority = i; size_t priority = i;

View File

@ -34,7 +34,7 @@ Paths::Paths(const CmdLineArgs& args)
#ifdef INSTALLED_DATADIR #ifdef INSTALLED_DATADIR
m_rdata = WIDEN(STRINGIZE(INSTALLED_DATADIR)) L"/"; m_rdata = WIDEN(STRINGIZE(INSTALLED_DATADIR)) L"/";
#else #else
m_rdata = Path::Join(m_root, L"data/"); m_rdata = Path::Join(m_root, "data/");
#endif #endif
const wchar_t* subdirectoryName = args.Has("writableRoot")? 0 : L"0ad"; const wchar_t* subdirectoryName = args.Has("writableRoot")? 0 : L"0ad";
@ -43,29 +43,29 @@ Paths::Paths(const CmdLineArgs& args)
if(!subdirectoryName) if(!subdirectoryName)
{ {
m_data = m_rdata; m_data = m_rdata;
m_config = Path::Join(m_data, L"config/"); m_config = Path::Join(m_data, "config/");
m_cache = Path::Join(m_data, L"cache/"); m_cache = Path::Join(m_data, "cache/");
m_logs = Path::Join(m_root, L"logs/"); m_logs = Path::Join(m_root, "logs/");
} }
else else
{ {
#if OS_WIN #if OS_WIN
const NativePath appdata = Path::AddSlash(Path::Join(wutil_AppdataPath(), subdirectoryName)); const NativePath appdata = Path::AddSlash(Path::Join(wutil_AppdataPath(), NativePath(subdirectoryName)));
m_data = Path::Join(appdata, L"data/"); m_data = Path::Join(appdata, "data/");
m_config = Path::Join(appdata, L"config/"); m_config = Path::Join(appdata, "config/");
m_cache = Path::Join(appdata, L"cache/"); m_cache = Path::Join(appdata, "cache/");
m_logs = Path::Join(appdata, L"logs/"); m_logs = Path::Join(appdata, "logs/");
#else #else
const char* envHome = getenv("HOME"); const char* envHome = getenv("HOME");
debug_assert(envHome); debug_assert(envHome);
const NativePath home(wstring_from_utf8(envHome)); const NativePath home(wstring_from_utf8(envHome));
const NativePath xdgData = XDG_Path("XDG_DATA_HOME", home, Path::Join(home, L".local/share/", subdirectoryName)); const NativePath xdgData = XDG_Path("XDG_DATA_HOME", home, Path::Join(home, ".local/share/"), subdirectoryName));
const NativePath xdgConfig = XDG_Path("XDG_CONFIG_HOME", home, Path::Join(home, L".config/", subdirectoryName)); const NativePath xdgConfig = XDG_Path("XDG_CONFIG_HOME", home, Path::Join(home, ".config/"), subdirectoryName));
const NativePath xdgCache = XDG_Path("XDG_CACHE_HOME", home, Path::Join(home, L".cache/", subdirectoryName)); const NativePath xdgCache = XDG_Path("XDG_CACHE_HOME", home, Path::Join(home, ".cache/"), subdirectoryName));
m_data = Path::AddSlash(xdgData); m_data = Path::AddSlash(xdgData);
m_cache = Path::AddSlash(xdgCache); m_cache = Path::AddSlash(xdgCache);
m_config = Path::AddSlash(Path::Join(xdgConfig, L"config")); m_config = Path::AddSlash(Path::Join(xdgConfig, "config"));
m_logs = Path::AddSlash(Path::Join(xdgConfig, L"logs")); m_logs = Path::AddSlash(Path::Join(xdgConfig, "logs"));
#endif #endif
} }
} }
@ -103,8 +103,8 @@ Paths::Paths(const CmdLineArgs& args)
if(path) if(path)
{ {
if(path[0] != '/') // relative to $HOME if(path[0] != '/') // relative to $HOME
return Path::AddSlash(Path::Join(home, wstring_from_utf8(path))); return Path::AddSlash(Path::Join(home, path));
return Path::AddSlash(wstring_from_utf8(path)); return Path::AddSlash(NativePathFromString(path));
} }
return Path::AddSlash(defaultPath); return Path::AddSlash(defaultPath);
} }

View File

@ -526,7 +526,7 @@ void CProfileViewer::SaveToFile()
{ {
// Open the file. (It will be closed when the CProfileViewer // Open the file. (It will be closed when the CProfileViewer
// destructor is called.) // destructor is called.)
NativePath path = Path::Join(psLogDir(), L"profile.txt"); NativePath path = Path::Join(psLogDir(), "profile.txt");
m->outputStream.open(utf8_from_wstring(path).c_str(), std::ofstream::out | std::ofstream::trunc); m->outputStream.open(utf8_from_wstring(path).c_str(), std::ofstream::out | std::ofstream::trunc);
if (m->outputStream.fail()) if (m->outputStream.fail())

View File

@ -77,12 +77,12 @@ void psBundleLogs(FILE* f)
fwprintf(f, L"SVN Revision: %ls\n\n", svn_revision); fwprintf(f, L"SVN Revision: %ls\n\n", svn_revision);
fwprintf(f, L"System info:\n\n"); fwprintf(f, L"System info:\n\n");
NativePath path1 = Path::Join(psLogDir(), L"system_info.txt"); NativePath path1 = Path::Join(psLogDir(), "system_info.txt");
AppendAsciiFile(f, path1); AppendAsciiFile(f, path1);
fwprintf(f, L"\n\n====================================\n\n"); fwprintf(f, L"\n\n====================================\n\n");
fwprintf(f, L"Main log:\n\n"); fwprintf(f, L"Main log:\n\n");
NativePath path2 = Path::Join(psLogDir(), L"mainlog.html"); NativePath path2 = Path::Join(psLogDir(), "mainlog.html");
AppendAsciiFile(f, path2); AppendAsciiFile(f, path2);
fwprintf(f, L"\n\n====================================\n\n"); fwprintf(f, L"\n\n====================================\n\n");
} }

View File

@ -68,7 +68,7 @@ CReplayLogger::CReplayLogger(ScriptInterface& scriptInterface) :
name << L"/commands.txt"; name << L"/commands.txt";
NativePath path = Path::Join(psLogDir(), name.str()); NativePath path = Path::Join(psLogDir(), NativePath(name.str()));
CreateDirectories(Path::Path(path), 0700); CreateDirectories(Path::Path(path), 0700);
m_Stream = new std::ofstream(StringFromNativePath(path).c_str(), std::ofstream::out | std::ofstream::trunc); m_Stream = new std::ofstream(StringFromNativePath(path).c_str(), std::ofstream::out | std::ofstream::trunc);
} }

View File

@ -78,7 +78,7 @@ void WriteSystemInfo()
struct utsname un; struct utsname un;
uname(&un); uname(&un);
NativePath pathname = Path::Join(psLogDir(), L"system_info.txt"); NativePath pathname = Path::Join(psLogDir(), "system_info.txt");
FILE* f; FILE* f;
errno_t err = _wfopen_s(&f, pathname.c_str(), L"w"); errno_t err = _wfopen_s(&f, pathname.c_str(), L"w");
if(err != 0) if(err != 0)

View File

@ -70,7 +70,7 @@ void CWorld::RegisterInit(const CStrW& mapFile, int playerID)
// Load the map, if one was specified // Load the map, if one was specified
if (mapFile.length()) if (mapFile.length())
{ {
VfsPath mapfilename(Path::Join(L"maps/scenarios/", mapFile + L".pmp")); VfsPath mapfilename(Path::Join("maps/scenarios", NativePath(mapFile + L".pmp")));
CMapReader* reader = 0; CMapReader* reader = 0;
try try

View File

@ -118,7 +118,7 @@ bool CXeromyces::GenerateCachedXMB(const PIVFS& vfs, const VfsPath& sourcePath,
archiveCachePath = cacheLoader.ArchiveCachePath(sourcePath); archiveCachePath = cacheLoader.ArchiveCachePath(sourcePath);
return (ConvertFile(vfs, sourcePath, Path::Join(L"cache", archiveCachePath)) == PSRETURN_OK); return (ConvertFile(vfs, sourcePath, Path::Join("cache", archiveCachePath)) == PSRETURN_OK);
} }
PSRETURN CXeromyces::ConvertFile(const PIVFS& vfs, const VfsPath& filename, const VfsPath& xmbPath) PSRETURN CXeromyces::ConvertFile(const PIVFS& vfs, const VfsPath& filename, const VfsPath& xmbPath)

View File

@ -1624,7 +1624,7 @@ int CRenderer::LoadAlphaMaps()
{ {
// note: these individual textures can be discarded afterwards; // note: these individual textures can be discarded afterwards;
// we cache the composite. // we cache the composite.
textures[i] = ogl_tex_load(g_VFS, Path::Join(path, fnames[i])); textures[i] = ogl_tex_load(g_VFS, Path::Join(path, VfsPath(fnames[i])));
RETURN_ERR(textures[i]); RETURN_ERR(textures[i]);
// get its size and make sure they are all equal. // get its size and make sure they are all equal.

View File

@ -75,7 +75,7 @@ void SkyManager::LoadSkyTextures()
{ {
for (size_t i = 0; i < ARRAY_SIZE(m_SkyTexture); ++i) for (size_t i = 0; i < ARRAY_SIZE(m_SkyTexture); ++i)
{ {
VfsPath path = Path::Join(L"art/textures/skies", m_SkySet, std::wstring(s_imageNames[i])+L".dds"); VfsPath path = Path::Join("art/textures/skies", Path::Join(NativePath(m_SkySet), NativePath(s_imageNames[i])+L".dds"));
CTextureProperties textureProps(path); CTextureProperties textureProps(path);
textureProps.SetWrap(GL_CLAMP_TO_EDGE); textureProps.SetWrap(GL_CLAMP_TO_EDGE);

View File

@ -275,12 +275,17 @@ JSBool GetBuildTimestamp(JSContext* cx, uintN argc, jsval* vp)
} }
#ifdef DEBUG #ifdef DEBUG
void DumpHeap(const char* name, int idx, JSContext* cx) void DumpHeap(const char* basename, int idx, JSContext* cx)
{ {
wchar_t buf[64]; char filename[64];
swprintf_s(buf, ARRAY_SIZE(buf), L"%hs.%03d.txt", name, idx); sprintf_s(filename, ARRAY_SIZE(filename), "%hs.%03d.txt", basename, idx);
NativePath path = Path::Join(psLogDir(), buf); NativePath pathname = Path::Join(psLogDir(), filename);
FILE* f = fopen(utf8_from_wstring(path).c_str(), "w"); #if OS_WIN
FILE* f = _wfopen(pathname.c_str(), L"w");
#else
std::string pathname8 = StringFromNativePath(pathname);
FILE* f = fopen(pathname8.c_str(), "w");
#endif
debug_assert(f); debug_assert(f);
JS_DumpHeap(cx, f, NULL, 0, NULL, (size_t)-1, NULL); JS_DumpHeap(cx, f, NULL, 0, NULL, (size_t)-1, NULL);
fclose(f); fclose(f);

View File

@ -289,7 +289,7 @@ void CSimulation2Impl::DumpState()
std::wstringstream name; std::wstringstream name;
name << L"sim_log/" << getpid() << L"/" << std::setw(5) << std::setfill(L'0') << m_TurnNumber << L".txt"; name << L"sim_log/" << getpid() << L"/" << std::setw(5) << std::setfill(L'0') << m_TurnNumber << L".txt";
NativePath path = Path::Join(psLogDir(), name.str()); NativePath path = Path::Join(psLogDir(), NativePath(name.str()));
CreateDirectories(Path::Path(path), 0700); CreateDirectories(Path::Path(path), 0700);
std::ofstream file (StringFromNativePath(path).c_str(), std::ofstream::out | std::ofstream::trunc); std::ofstream file (StringFromNativePath(path).c_str(), std::ofstream::out | std::ofstream::trunc);

View File

@ -320,7 +320,7 @@ bool CCmpTemplateManager::LoadTemplateFile(const std::string& templateName, int
// Normal case: templateName is an XML file: // Normal case: templateName is an XML file:
VfsPath path = Path::Join(TEMPLATE_ROOT, wstring_from_utf8(templateName + ".xml")); VfsPath path = Path::Join(VfsPath(TEMPLATE_ROOT), NativePathFromString(templateName + ".xml"));
CXeromyces xero; CXeromyces xero;
PSRETURN ok = xero.Load(g_VFS, path); PSRETURN ok = xero.Load(g_VFS, path);
if (ok != PSRETURN_OK) if (ok != PSRETURN_OK)

View File

@ -36,8 +36,8 @@ public:
CXeromyces::Startup(); CXeromyces::Startup();
g_VFS = CreateVfs(20 * MiB); g_VFS = CreateVfs(20 * MiB);
TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), L"mods/public"), VFS_MOUNT_MUST_EXIST)); TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), "mods/public"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"cache/", Path::Join(DataDir(), L"cache"))); TS_ASSERT_OK(g_VFS->Mount(L"cache/", Path::Join(DataDir(), "cache")));
// Need some stuff for terrain movement costs: // Need some stuff for terrain movement costs:
// (TODO: this ought to be independent of any graphics code) // (TODO: this ought to be independent of any graphics code)

View File

@ -25,7 +25,7 @@ public:
void setUp() void setUp()
{ {
g_VFS = CreateVfs(20 * MiB); g_VFS = CreateVfs(20 * MiB);
g_VFS->Mount(L"", Path::Join(DataDir(), L"mods/public"), VFS_MOUNT_MUST_EXIST); // ignore directory-not-found errors g_VFS->Mount(L"", Path::Join(DataDir(), "mods/public"), VFS_MOUNT_MUST_EXIST); // ignore directory-not-found errors
CXeromyces::Startup(); CXeromyces::Startup();
} }

View File

@ -940,7 +940,7 @@ CScriptVal CComponentManager::Script_ReadJSONFile(void* cbdata, std::string file
{ {
CComponentManager* componentManager = static_cast<CComponentManager*> (cbdata); CComponentManager* componentManager = static_cast<CComponentManager*> (cbdata);
NativePath path = L"simulation/data/" + wstring_from_utf8(fileName); NativePath path = Path::Join("simulation/data", NativePathFromString(fileName));
return componentManager->GetScriptInterface().ReadJSONFile(path).get(); return componentManager->GetScriptInterface().ReadJSONFile(path).get();
} }

View File

@ -37,8 +37,8 @@ public:
void setUp() void setUp()
{ {
g_VFS = CreateVfs(20 * MiB); g_VFS = CreateVfs(20 * MiB);
TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), L"mods/_test.sim"), VFS_MOUNT_MUST_EXIST)); TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), "mods/_test.sim"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"cache", Path::Join(DataDir(), L"_testcache"))); TS_ASSERT_OK(g_VFS->Mount(L"cache", Path::Join(DataDir(), "_testcache")));
CXeromyces::Startup(); CXeromyces::Startup();
} }
@ -46,7 +46,7 @@ public:
{ {
CXeromyces::Terminate(); CXeromyces::Terminate();
g_VFS.reset(); g_VFS.reset();
DeleteDirectory(Path::Join(DataDir(), L"_testcache")); DeleteDirectory(Path::Join(DataDir(), "_testcache"));
} }
void test_LoadTemplate() void test_LoadTemplate()
@ -223,8 +223,8 @@ public:
void setUp() void setUp()
{ {
g_VFS = CreateVfs(20 * MiB); g_VFS = CreateVfs(20 * MiB);
TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), L"mods/public"), VFS_MOUNT_MUST_EXIST)); TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), "mods/public"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"cache", Path::Join(DataDir(), L"_testcache"))); TS_ASSERT_OK(g_VFS->Mount(L"cache", Path::Join(DataDir(), "_testcache")));
CXeromyces::Startup(); CXeromyces::Startup();
} }
@ -232,7 +232,7 @@ public:
{ {
CXeromyces::Terminate(); CXeromyces::Terminate();
g_VFS.reset(); g_VFS.reset();
DeleteDirectory(Path::Join(DataDir(), L"_testcache")); DeleteDirectory(Path::Join(DataDir(), "_testcache"));
} }
// This just attempts loading every public entity, to check there's no validation errors // This just attempts loading every public entity, to check there's no validation errors

View File

@ -44,8 +44,8 @@ public:
void setUp() void setUp()
{ {
g_VFS = CreateVfs(20 * MiB); g_VFS = CreateVfs(20 * MiB);
TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), L"mods/_test.sim"), VFS_MOUNT_MUST_EXIST)); TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), "mods/_test.sim"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"cache", Path::Join(DataDir(), L"_testcache"))); TS_ASSERT_OK(g_VFS->Mount(L"cache", Path::Join(DataDir(), "_testcache")));
CXeromyces::Startup(); CXeromyces::Startup();
} }
@ -53,7 +53,7 @@ public:
{ {
CXeromyces::Terminate(); CXeromyces::Terminate();
g_VFS.reset(); g_VFS.reset();
DeleteDirectory(Path::Join(DataDir(), L"_testcache")); DeleteDirectory(Path::Join(DataDir(), "_testcache"));
} }
void test_Load() void test_Load()

View File

@ -487,8 +487,8 @@ public:
CXeromyces::Startup(); CXeromyces::Startup();
g_VFS = CreateVfs(20 * MiB); g_VFS = CreateVfs(20 * MiB);
TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), L"mods/public"), VFS_MOUNT_MUST_EXIST)); TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), "mods/public"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"cache/", Path::Join(DataDir(), L"cache"))); TS_ASSERT_OK(g_VFS->Mount(L"cache/", Path::Join(DataDir(), "cache")));
CTerrain terrain; CTerrain terrain;

View File

@ -42,8 +42,8 @@ public:
void setUp() void setUp()
{ {
g_VFS = CreateVfs(20 * MiB); g_VFS = CreateVfs(20 * MiB);
TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), L"mods/_test.sim"), VFS_MOUNT_MUST_EXIST)); TS_ASSERT_OK(g_VFS->Mount(L"", Path::Join(DataDir(), "mods/_test.sim"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"cache", Path::Join(DataDir(), L"_testcache"))); TS_ASSERT_OK(g_VFS->Mount(L"cache", Path::Join(DataDir(), "_testcache")));
CXeromyces::Startup(); CXeromyces::Startup();
} }
@ -51,7 +51,7 @@ public:
{ {
CXeromyces::Terminate(); CXeromyces::Terminate();
g_VFS.reset(); g_VFS.reset();
DeleteDirectory(Path::Join(DataDir(), L"_testcache")); DeleteDirectory(Path::Join(DataDir(), "_testcache"));
} }
void test_AddEntity() void test_AddEntity()
@ -130,7 +130,7 @@ public:
{ {
CSimulation2 sim(NULL, &m_Terrain); CSimulation2 sim(NULL, &m_Terrain);
TS_ASSERT_OK(CreateDirectories(Path::Join(DataDir(), L"mods/_test.sim/simulation/components/hotload/"), 0700)); TS_ASSERT_OK(CreateDirectories(Path::Join(DataDir(), "mods/_test.sim/simulation/components/hotload/"), 0700));
copyFile(L"simulation/components/test-hotload1.js", L"simulation/components/hotload/hotload.js"); copyFile(L"simulation/components/test-hotload1.js", L"simulation/components/hotload/hotload.js");
TS_ASSERT_OK(g_VFS->Invalidate(L"simulation/components/hotload/hotload.js")); TS_ASSERT_OK(g_VFS->Invalidate(L"simulation/components/hotload/hotload.js"));
@ -155,7 +155,7 @@ public:
TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (sim.QueryInterface(ent, IID_Test1))->GetX(), 1000); TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (sim.QueryInterface(ent, IID_Test1))->GetX(), 1000);
TS_ASSERT_OK(DeleteDirectory(Path::Join(DataDir(), L"mods/_test.sim/simulation/components/hotload/"))); TS_ASSERT_OK(DeleteDirectory(Path::Join(DataDir(), "mods/_test.sim/simulation/components/hotload/")));
TS_ASSERT_OK(g_VFS->Invalidate(L"simulation/components/hotload/hotload.js")); TS_ASSERT_OK(g_VFS->Invalidate(L"simulation/components/hotload/hotload.js"));
TS_ASSERT_OK(sim.ReloadChangedFile(L"simulation/components/hotload/hotload.js")); TS_ASSERT_OK(sim.ReloadChangedFile(L"simulation/components/hotload/hotload.js"));

View File

@ -96,7 +96,7 @@ NativePath DataDir()
{ {
NativePath path; NativePath path;
TS_ASSERT_OK(sys_get_executable_name(path)); TS_ASSERT_OK(sys_get_executable_name(path));
return Path::Join(Path::Path(path), L"../data"); return Path::Join(Path::Path(path), "../data");
} }
// Script-based testing setup: // Script-based testing setup:
@ -115,7 +115,7 @@ void ScriptTestSetup(ScriptInterface& ifc)
// Load the TS_* function definitions // Load the TS_* function definitions
// (We don't use VFS because tests might not have the normal VFS paths loaded) // (We don't use VFS because tests might not have the normal VFS paths loaded)
NativePath path = Path::Join(DataDir(), L"tests/test_setup.js"); NativePath path = Path::Join(DataDir(), "tests/test_setup.js");
std::ifstream ifs(StringFromNativePath(path).c_str()); std::ifstream ifs(StringFromNativePath(path).c_str());
debug_assert(ifs.good()); debug_assert(ifs.good());
std::string content((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>()); std::string content((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());

View File

@ -100,7 +100,7 @@ MESSAGEHANDLER(LoadMap)
MESSAGEHANDLER(SaveMap) MESSAGEHANDLER(SaveMap)
{ {
CMapWriter writer; CMapWriter writer;
const VfsPath pathname = Path::Join(L"maps/scenarios/", *msg->filename); const VfsPath pathname = Path::Join("maps/scenarios", *msg->filename);
writer.SaveMap(pathname, writer.SaveMap(pathname,
g_Game->GetWorld()->GetTerrain(), g_Game->GetWorld()->GetTerrain(),
g_Renderer.GetWaterManager(), g_Renderer.GetSkyManager(), g_Renderer.GetWaterManager(), g_Renderer.GetSkyManager(),