1
0
forked from 0ad/0ad

refactor path interface:

- use wrapper class instead of std::wstring (reduces mixing of
strings/paths; allows safe+easy join via operator/ and convenient
case-insensitive comparison via operator==, avoids NativePathFromString,
similar to boost::filesystem)
- NativePath -> OsPath
- add hash and To/FromJSVal for Path
- add TS_ASSERT_PATH_EQUALS
- replace _wfopen_s with sys_OpenFile
- remove obsolete SortFiles/Directories

This was SVN commit r9107.
This commit is contained in:
janwas 2011-03-23 13:36:20 +00:00
parent e39fb7d0de
commit dcd192cb60
147 changed files with 948 additions and 1003 deletions

View File

@ -203,11 +203,11 @@ VfsPath CColladaManager::GetLoadableFilename(const VfsPath& pathnameNoExtension,
// (TODO: the comments and variable names say "pmd" but actually they can
// be "psa" too.)
VfsPath dae(Path::ChangeExtension(pathnameNoExtension, L".dae"));
VfsPath dae(pathnameNoExtension.ChangeExtension(L".dae"));
if (! VfsFileExists(dae))
{
// No .dae - got to use the .pmd, assuming there is one
return Path::ChangeExtension(pathnameNoExtension, extn);
return pathnameNoExtension.ChangeExtension(extn);
}
// There is a .dae - see if there's an up-to-date cached copy
@ -216,7 +216,7 @@ VfsPath CColladaManager::GetLoadableFilename(const VfsPath& pathnameNoExtension,
if (g_VFS->GetFileInfo(dae, &fileInfo) < 0)
{
// This shouldn't occur for any sensible reasons
LOGERROR(L"Failed to stat DAE file '%ls'", dae.c_str());
LOGERROR(L"Failed to stat DAE file '%ls'", dae.string().c_str());
return VfsPath();
}
@ -240,16 +240,16 @@ VfsPath CColladaManager::GetLoadableFilename(const VfsPath& pathnameNoExtension,
extension += extn;
// realDaePath_ is "[..]/mods/whatever/art/meshes/whatever.dae"
std::wstring realDaePath_;
OsPath realDaePath_;
LibError ret = g_VFS->GetRealPath(dae, realDaePath_);
debug_assert(ret == INFO::OK);
wchar_t realDaeBuf[PATH_MAX];
wcscpy_s(realDaeBuf, ARRAY_SIZE(realDaeBuf), realDaePath_.c_str());
wcscpy_s(realDaeBuf, ARRAY_SIZE(realDaeBuf), realDaePath_.string().c_str());
const wchar_t* realDaePath = wcsstr(realDaeBuf, L"mods/");
// cachedPmdVfsPath is "cache/mods/whatever/art/meshes/whatever_{hash}.pmd"
VfsPath cachedPmdVfsPath = Path::Join("cache", VfsPath(realDaePath));
cachedPmdVfsPath = Path::ChangeExtension(cachedPmdVfsPath, extension);
VfsPath cachedPmdVfsPath = VfsPath("cache") / realDaePath;
cachedPmdVfsPath = cachedPmdVfsPath.ChangeExtension(extension);
// If it's not in the cache, we'll have to create it first
if (! VfsFileExists(cachedPmdVfsPath))

View File

@ -58,10 +58,10 @@ bool CMapGenerator::GenerateMap(const VfsPath& scriptFile, const CScriptValRoote
return false;
// Load RMS
LOGMESSAGE(L"Loading RMS '%ls'", scriptFile.c_str());
LOGMESSAGE(L"Loading RMS '%ls'", scriptFile.string().c_str());
if (!m_ScriptInterface.LoadGlobalScriptFile(scriptFile))
{
LOGERROR(L"Failed to load RMS '%ls'", scriptFile.c_str());
LOGERROR(L"Failed to load RMS '%ls'", scriptFile.string().c_str());
return false;
}
@ -108,17 +108,17 @@ bool CMapGenerator::LoadScripts(const std::wstring& libraryName)
// Load all scripts in mapgen directory
if (fs_util::GetPathnames(g_VFS, path, L"*.js", pathnames) < 0)
{
LOGERROR(L"Error reading scripts in directory '%ls'", path.c_str());
LOGERROR(L"Error reading scripts in directory '%ls'", path.string().c_str());
return false;
}
for (VfsPaths::iterator it = pathnames.begin(); it != pathnames.end(); ++it)
{
LOGMESSAGE(L"Loading map generator script '%ls'", it->c_str());
LOGMESSAGE(L"Loading map generator script '%ls'", it->string().c_str());
if (!m_ScriptInterface.LoadGlobalScriptFile(*it))
{
LOGERROR(L"Failed to load script '%ls'", it->c_str());
LOGERROR(L"Failed to load script '%ls'", it->string().c_str());
return false;
}
}

View File

@ -72,7 +72,7 @@ void CMapReader::LoadMap(const VfsPath& pathname, CTerrain *pTerrain_,
m_CameraStartupTarget = INVALID_ENTITY;
filename_xml = Path::ChangeExtension(pathname, L".xml");
filename_xml = pathname.ChangeExtension(L".xml");
// In some cases (particularly tests) we don't want to bother storing a large
// mostly-empty .pmp file, so we let the XML file specify basic terrain instead.
@ -310,7 +310,7 @@ int CMapReader::ApplyData()
PSRETURN CMapSummaryReader::LoadMap(const VfsPath& pathname)
{
VfsPath filename_xml = Path::ChangeExtension(pathname, L".xml");
VfsPath filename_xml = pathname.ChangeExtension(L".xml");
CXeromyces xmb_file;
if (xmb_file.Load(g_VFS, filename_xml) != PSRETURN_OK)

View File

@ -62,7 +62,7 @@ void CMapWriter::SaveMap(const VfsPath& pathname, CTerrain* pTerrain,
// write it out
packer.Write(pathname);
VfsPath pathnameXML = Path::ChangeExtension(pathname, L".xml");
VfsPath pathnameXML = pathname.ChangeExtension(L".xml");
WriteXML(pathnameXML, pWaterMan, pSkyMan, pLightEnv, pCamera, pCinema, pSimulation2);
}

View File

@ -40,7 +40,7 @@ CMeshManager::~CMeshManager()
CModelDefPtr CMeshManager::GetMesh(const VfsPath& pathname)
{
const VfsPath name = Path::ChangeExtension(pathname, L"");
const VfsPath name = pathname.ChangeExtension(L"");
// Find the mesh if it's already been loaded and cached
mesh_map::iterator iter = m_MeshMap.find(name);
@ -53,7 +53,7 @@ CModelDefPtr CMeshManager::GetMesh(const VfsPath& pathname)
if (pmdFilename.empty())
{
LOGERROR(L"Could not load mesh '%ls'", pathname.c_str());
LOGERROR(L"Could not load mesh '%ls'", pathname.string().c_str());
return CModelDefPtr();
}
@ -65,7 +65,7 @@ CModelDefPtr CMeshManager::GetMesh(const VfsPath& pathname)
}
catch (PSERROR_File&)
{
LOGERROR(L"Could not load mesh '%ls'", pathname.c_str());
LOGERROR(L"Could not load mesh '%ls'", pathname.string().c_str());
return CModelDefPtr();
}
}

View File

@ -18,11 +18,10 @@
#ifndef INCLUDED_MESHMANAGER
#define INCLUDED_MESHMANAGER
#include "ps/CStr.h"
#include "lib/file/vfs/vfs_path.h"
#include "lib/sysdep/stl.h"
#include <boost/shared_ptr.hpp>
#include <boost/unordered_map.hpp>
#include <boost/weak_ptr.hpp>
class CModelDef;
@ -40,7 +39,7 @@ public:
CModelDefPtr GetMesh(const VfsPath& pathname);
private:
typedef STL_HASH_MAP<CStrW, boost::weak_ptr<CModelDef>, CStrW_hash_compare> mesh_map;
typedef boost::unordered_map<VfsPath, boost::weak_ptr<CModelDef> > mesh_map;
mesh_map m_MeshMap;
CColladaManager& m_ColladaManager;
};

View File

@ -90,7 +90,7 @@ bool CObjectBase::Load(const VfsPath& pathname)
m_VariantGroups.clear();
m_Pathname = pathname;
m_ShortName = Path::Basename(pathname);
m_ShortName = pathname.Basename().string();
// Set up the vector<vector<T>> m_Variants to contain the right number
@ -142,11 +142,11 @@ bool CObjectBase::Load(const VfsPath& pathname)
if (option_name == el_mesh)
{
currentVariant->m_ModelFilename = Path::Join("art/meshes", option.GetText().FromUTF8());
currentVariant->m_ModelFilename = VfsPath("art/meshes") / option.GetText().FromUTF8();
}
else if (option_name == el_texture)
{
currentVariant->m_TextureFilename = Path::Join("art/textures/skins", option.GetText().FromUTF8());
currentVariant->m_TextureFilename = VfsPath("art/textures/skins") / option.GetText().FromUTF8();
}
else if (option_name == el_decal)
{
@ -178,7 +178,7 @@ bool CObjectBase::Load(const VfsPath& pathname)
}
else if (ae.Name == at_file)
{
anim.m_FileName = Path::Join("art/animation", ae.Value.FromUTF8());
anim.m_FileName = VfsPath("art/animation") / ae.Value.FromUTF8();
}
else if (ae.Name == at_speed)
{
@ -224,7 +224,7 @@ bool CObjectBase::Load(const VfsPath& pathname)
if (currentGroup->size() == 0)
{
LOGERROR(L"Actor group has zero variants ('%ls')", pathname.c_str());
LOGERROR(L"Actor group has zero variants ('%ls')", pathname.string().c_str());
}
++currentGroup;
@ -239,7 +239,7 @@ bool CObjectBase::Load(const VfsPath& pathname)
}
else if (child_name == el_material)
{
m_Material = Path::Join("art/materials", child.GetText().FromUTF8());
m_Material = VfsPath("art/materials") / child.GetText().FromUTF8();
}
}

View File

@ -55,7 +55,7 @@ public:
// name of the prop point to attach to - "Prop01", "Prop02", "Head", "LeftHand", etc ..
CStr m_PropPointName;
// name of the model file - art/actors/props/sword.xml or whatever
VfsPath m_ModelName;
CStrW m_ModelName;
};
struct Decal

View File

@ -103,7 +103,7 @@ bool CObjectEntry::BuildVariation(const std::vector<std::set<CStr> >& selections
CModelDefPtr modeldef (objectManager.GetMeshManager().GetMesh(m_ModelName));
if (!modeldef)
{
LOGERROR(L"CObjectEntry::BuildVariation(): Model %ls failed to load", m_ModelName.c_str());
LOGERROR(L"CObjectEntry::BuildVariation(): Model %ls failed to load", m_ModelName.string().c_str());
return false;
}
@ -161,7 +161,7 @@ bool CObjectEntry::BuildVariation(const std::vector<std::set<CStr> >& selections
{
// start up idling
if (!model->SetAnimation(GetRandomAnimation("idle")))
LOGERROR(L"Failed to set idle animation in model \"%ls\"", m_ModelName.c_str());
LOGERROR(L"Failed to set idle animation in model \"%ls\"", m_ModelName.string().c_str());
}
// build props - TODO, RC - need to fix up bounds here
@ -211,7 +211,7 @@ bool CObjectEntry::BuildVariation(const std::vector<std::set<CStr> >& selections
propmodel->ToCModel()->SetAnimation(oe->GetRandomAnimation("idle"));
}
else
LOGERROR(L"Failed to find matching prop point called \"%hs\" in model \"%ls\" for actor \"%ls\"", ppn.c_str(), m_ModelName.c_str(), m_Base->m_ShortName.c_str());
LOGERROR(L"Failed to find matching prop point called \"%hs\" in model \"%ls\" for actor \"%ls\"", ppn.c_str(), m_ModelName.string().c_str(), m_Base->m_ShortName.c_str());
}
// setup flags

View File

@ -55,7 +55,7 @@ public:
// so we can have lots of colour variations without wasting memory on
// lots of objectEntries)
CStrW m_ProjectileModelName;
std::wstring m_ProjectileModelName;
// Returns a randomly-chosen animation matching the given name.
// If none is found, returns NULL.

View File

@ -85,7 +85,7 @@ CObjectBase* CObjectManager::FindObjectBase(const CStrW& objectname)
CObjectBase* obj = new CObjectBase(*this);
VfsPath pathname = Path::Join("art/actors/", objectname);
VfsPath pathname = VfsPath("art/actors/") / objectname;
if (obj->Load(pathname))
{
@ -123,7 +123,7 @@ CObjectEntry* CObjectManager::FindObjectVariation(CObjectBase* base, const std::
// Look to see whether this particular variation has already been loaded
std::vector<u8> choices = base->CalculateVariationKey(selections);
ObjectKey key (base->m_Pathname, choices);
ObjectKey key (base->m_Pathname.string(), choices);
std::map<ObjectKey, CObjectEntry*>::iterator it = m_Objects.find(key);
if (it != m_Objects.end())

View File

@ -108,11 +108,11 @@ bool CEmitter::LoadXml(const VfsPath& pathname)
if( root.GetNodeName() != el_Emitter )
{
LOGERROR(L"CEmitter::LoadXml: XML root was not \"Emitter\" in file %ls. Load failed.", pathname.c_str() );
LOGERROR(L"CEmitter::LoadXml: XML root was not \"Emitter\" in file %ls. Load failed.", pathname.string().c_str() );
return( false );
}
m_tag = Path::Basename(pathname);
m_tag = pathname.Basename().string();
//TODO figure out if we need to use Type attribute to construct different emitter types,
// probably have to move some of this code into a static factory method or out into ParticleEngine class

View File

@ -51,7 +51,7 @@ CSkeletonAnimManager::~CSkeletonAnimManager()
// doesn't refer to valid animation file
CSkeletonAnimDef* CSkeletonAnimManager::GetAnimation(const VfsPath& pathname)
{
VfsPath name = Path::ChangeExtension(pathname, L"");
VfsPath name = pathname.ChangeExtension(L"");
// Find if it's already been loaded
boost::unordered_map<VfsPath, CSkeletonAnimDef*>::iterator iter = m_Animations.find(name);
@ -65,7 +65,7 @@ CSkeletonAnimDef* CSkeletonAnimManager::GetAnimation(const VfsPath& pathname)
if (psaFilename.empty())
{
LOGERROR(L"Could not load animation '%ls'", pathname.c_str());
LOGERROR(L"Could not load animation '%ls'", pathname.string().c_str());
def = NULL;
}
else
@ -81,9 +81,9 @@ CSkeletonAnimDef* CSkeletonAnimManager::GetAnimation(const VfsPath& pathname)
}
if (def)
LOGMESSAGE(L"CSkeletonAnimManager::GetAnimation(%ls): Loaded successfully", pathname.c_str());
LOGMESSAGE(L"CSkeletonAnimManager::GetAnimation(%ls): Loaded successfully", pathname.string().c_str());
else
LOGERROR(L"CSkeletonAnimManager::GetAnimation(%ls): Failed loading, marked file as bad", pathname.c_str());
LOGERROR(L"CSkeletonAnimManager::GetAnimation(%ls): Failed loading, marked file as bad", pathname.string().c_str());
// Add to map
m_Animations[name] = def; // NULL if failed to load - we won't try loading it again

View File

@ -56,7 +56,7 @@ CTerrainPropertiesPtr CTerrainProperties::FromXML(const CTerrainPropertiesPtr& p
{
LOGERROR(
L"TerrainProperties: Loading %ls: Root node is not terrains (found \"%hs\")",
pathname.c_str(),
pathname.string().c_str(),
rootName.c_str());
return CTerrainPropertiesPtr();
}
@ -81,7 +81,7 @@ CTerrainPropertiesPtr CTerrainProperties::FromXML(const CTerrainPropertiesPtr& p
{
LOGWARNING(
L"TerrainProperties: Loading %ls: Unexpected node %hs\n",
pathname.c_str(),
pathname.string().c_str(),
XeroFile.GetElementString(child.GetNodeName()).c_str());
// Keep reading - typos shouldn't be showstoppers
}

View File

@ -19,6 +19,7 @@
#include <map>
#include "lib/utf8.h"
#include "lib/ogl.h"
#include "lib/path_util.h"
#include "lib/res/graphics/ogl_tex.h"
@ -54,7 +55,7 @@ CTerrainTextureEntry::CTerrainTextureEntry(CTerrainPropertiesPtr props, const Vf
for (;it!=m_Groups.end();++it)
(*it)->AddTerrain(this);
m_Tag = CStrW(Path::Basename(path)).ToUTF8();
m_Tag = utf8_from_wstring(path.Basename().string());
}
CTerrainTextureEntry::~CTerrainTextureEntry()

View File

@ -124,8 +124,9 @@ void CTerrainTextureManager::LoadTextures(const CTerrainPropertiesPtr& props, co
// 'real' texture name
for(size_t i = 0; i < pathnames.size(); i++)
{
if(boost::algorithm::ends_with(Path::Filename(pathnames[i]), L".cached.dds"))
pathnames[i] = Path::Join(Path::Path(pathnames[i]), boost::algorithm::erase_last_copy(Path::Filename(pathnames[i]), L".cached.dds"));
const std::wstring filename = pathnames[i].Filename().string();
if(boost::algorithm::ends_with(filename, L".cached.dds"))
pathnames[i] = pathnames[i].Parent() / boost::algorithm::erase_last_copy(filename, L".cached.dds");
}
// Remove any duplicates created by the stripping
@ -143,14 +144,14 @@ void CTerrainTextureManager::LoadTextures(const CTerrainPropertiesPtr& props, co
if(!tex_is_known_extension(pathnames[i]))
continue;
VfsPath pathnameXML = Path::ChangeExtension(pathnames[i], L".xml");
VfsPath pathnameXML = pathnames[i].ChangeExtension(L".xml");
CTerrainPropertiesPtr myprops;
// Has XML file -> attempt to load properties
if (VfsFileExists(pathnameXML))
{
myprops = GetPropertiesFromFile(props, pathnameXML);
if (myprops)
LOGMESSAGE(L"CTerrainTextureManager: Successfully loaded override xml %ls for texture %ls", pathnameXML.c_str(), pathnames[i].c_str());
LOGMESSAGE(L"CTerrainTextureManager: Successfully loaded override xml %ls for texture %ls", pathnameXML.string().c_str(), pathnames[i].string().c_str());
}
// Error or non-existant xml file -> use parent props
@ -163,19 +164,19 @@ void CTerrainTextureManager::LoadTextures(const CTerrainPropertiesPtr& props, co
void CTerrainTextureManager::RecurseDirectory(const CTerrainPropertiesPtr& parentProps, const VfsPath& path)
{
//LOGMESSAGE(L"CTextureManager::RecurseDirectory(%ls)", path.c_str());
//LOGMESSAGE(L"CTextureManager::RecurseDirectory(%ls)", path.string().c_str());
CTerrainPropertiesPtr props;
// Load terrains.xml first, if it exists
VfsPath pathname = Path::Join(path, "terrains.xml");
VfsPath pathname = path / "terrains.xml";
if (VfsFileExists(pathname))
props = GetPropertiesFromFile(parentProps, pathname);
// No terrains.xml, or read failures -> use parent props (i.e.
if (!props)
{
LOGMESSAGE(L"CTerrainTextureManager::RecurseDirectory(%ls): no terrains.xml (or errors while loading) - using parent properties", path.c_str());
LOGMESSAGE(L"CTerrainTextureManager::RecurseDirectory(%ls): no terrains.xml (or errors while loading) - using parent properties", path.string().c_str());
props = parentProps;
}
@ -184,7 +185,7 @@ void CTerrainTextureManager::RecurseDirectory(const CTerrainPropertiesPtr& paren
(void)g_VFS->GetDirectoryEntries(path, 0, &subdirectoryNames);
for (size_t i=0;i<subdirectoryNames.size();i++)
{
VfsPath subdirectoryPath = Path::AddSlash(Path::Join(path, subdirectoryNames[i]));
VfsPath subdirectoryPath = path / subdirectoryNames[i] / "";
RecurseDirectory(props, subdirectoryPath);
}

View File

@ -115,7 +115,7 @@ CTextureConverter::SettingsFile* CTextureConverter::LoadSettings(const VfsPath&
if (root.GetNodeName() != el_textures)
{
LOGERROR(L"Invalid texture settings file \"%ls\" (unrecognised root element)", path.c_str());
LOGERROR(L"Invalid texture settings file \"%ls\" (unrecognised root element)", path.string().c_str());
return NULL;
}
@ -317,14 +317,14 @@ bool CTextureConverter::ConvertTexture(const CTexturePtr& texture, const VfsPath
size_t fileSize;
if (m_VFS->LoadFile(src, file, fileSize) < 0)
{
LOGERROR(L"Failed to load texture \"%ls\"", src.c_str());
LOGERROR(L"Failed to load texture \"%ls\"", src.string().c_str());
return false;
}
Tex tex;
if (tex_decode(file, fileSize, &tex) < 0)
{
LOGERROR(L"Failed to decode texture \"%ls\"", src.c_str());
LOGERROR(L"Failed to decode texture \"%ls\"", src.string().c_str());
return false;
}
@ -334,7 +334,7 @@ bool CTextureConverter::ConvertTexture(const CTexturePtr& texture, const VfsPath
// Convert to uncompressed BGRA with no mipmaps
if (tex_transform_to(&tex, (tex.flags | TEX_BGR | TEX_ALPHA) & ~(TEX_DXT | TEX_MIPMAPS)) < 0)
{
LOGERROR(L"Failed to transform texture \"%ls\"", src.c_str());
LOGERROR(L"Failed to transform texture \"%ls\"", src.string().c_str());
tex_free(&tex);
return false;
}

View File

@ -171,7 +171,7 @@ public:
Handle h = ogl_tex_load(m_VFS, path, RES_UNIQUE);
if (h <= 0)
{
LOGERROR(L"Texture failed to load; \"%ls\"", texture->m_Properties.m_Path.c_str());
LOGERROR(L"Texture failed to load; \"%ls\"", texture->m_Properties.m_Path.string().c_str());
// Replace with error texture to make it obvious
texture->SetHandle(m_ErrorHandle);
@ -211,7 +211,7 @@ public:
// Upload to GL
if (!m_DisableGL && ogl_tex_upload(h) < 0)
{
LOGERROR(L"Texture failed to upload: \"%ls\"", texture->m_Properties.m_Path.c_str());
LOGERROR(L"Texture failed to upload: \"%ls\"", texture->m_Properties.m_Path.string().c_str());
ogl_tex_free(h);
@ -303,7 +303,7 @@ public:
CTexturePtr texture = CreateTexture(textureProps);
CTextureConverter::Settings settings = GetConverterSettings(texture);
if (!m_TextureConverter.ConvertTexture(texture, sourcePath, Path::Join("cache", archiveCachePath), settings))
if (!m_TextureConverter.ConvertTexture(texture, sourcePath, VfsPath("cache") / archiveCachePath, settings))
return false;
while (true)
@ -334,7 +334,7 @@ public:
}
else
{
LOGERROR(L"Texture failed to convert: \"%ls\"", texture->m_Properties.m_Path.c_str());
LOGERROR(L"Texture failed to convert: \"%ls\"", texture->m_Properties.m_Path.string().c_str());
texture->SetHandle(m_ErrorHandle);
}
texture->m_State = CTexture::LOADED;
@ -404,18 +404,18 @@ public:
*/
CTextureConverter::Settings GetConverterSettings(const CTexturePtr& texture)
{
fs::wpath srcPath = texture->m_Properties.m_Path;
fs::wpath srcPath = texture->m_Properties.m_Path.string();
std::vector<CTextureConverter::SettingsFile*> files;
VfsPath p;
for (fs::wpath::iterator it = srcPath.begin(); it != srcPath.end(); ++it)
{
VfsPath settingsPath = Path::Join(p, "textures.xml");
VfsPath settingsPath = p / "textures.xml";
m_HotloadFiles[settingsPath].insert(texture);
CTextureConverter::SettingsFile* f = GetSettingsFile(settingsPath);
if (f)
files.push_back(f);
p = Path::Join(p, *it);
p = p / *it;
}
return m_TextureConverter.ComputeSettings(srcPath.leaf(), files);
}

View File

@ -17,6 +17,7 @@
#include "lib/self_test.h"
#include "lib/file/file_system_util.h"
#include "lib/file/vfs/vfs.h"
#include "lib/file/io/io.h"
@ -27,17 +28,17 @@
#include "ps/CLogger.h"
#include "ps/XML/RelaxNG.h"
static NativePath MOD_PATH(Path::Join(DataDir(), "mods/_test.mesh"));
static NativePath CACHE_PATH(Path::Join(DataDir(), "_testcache"));
static OsPath MOD_PATH(DataDir()/"mods/_test.mesh");
static OsPath CACHE_PATH(DataDir()/"_testcache");
const wchar_t* srcDAE = L"collada/sphere.dae";
const wchar_t* srcPMD = L"collada/sphere.pmd";
const wchar_t* testDAE = L"art/skeletons/test.dae";
const wchar_t* testPMD = L"art/skeletons/test.pmd";
const wchar_t* testBase = L"art/skeletons/test";
const OsPath srcDAE(L"collada/sphere.dae");
const OsPath srcPMD(L"collada/sphere.pmd");
const OsPath testDAE(L"art/skeletons/test.dae");
const OsPath testPMD(L"art/skeletons/test.pmd");
const OsPath testBase(L"art/skeletons/test");
const wchar_t* srcSkeletonDefs = L"collada/skeletons.xml";
const wchar_t* testSkeletonDefs = L"art/skeletons/skeletons.xml";
const OsPath srcSkeletonDefs(L"collada/skeletons.xml");
const OsPath testSkeletonDefs(L"art/skeletons/skeletons.xml");
extern PIVFS g_VFS;
@ -51,15 +52,15 @@ class TestMeshManager : public CxxTest::TestSuite
// Make sure the required directories doesn't exist when we start,
// in case the previous test aborted and left them full of junk
if(DirectoryExists(MOD_PATH))
if(fs_util::DirectoryExists(MOD_PATH))
DeleteDirectory(MOD_PATH);
if(DirectoryExists(CACHE_PATH))
if(fs_util::DirectoryExists(CACHE_PATH))
DeleteDirectory(CACHE_PATH);
g_VFS = CreateVfs(20*MiB);
TS_ASSERT_OK(g_VFS->Mount(L"", MOD_PATH));
TS_ASSERT_OK(g_VFS->Mount(L"collada/", Path::Join(DataDir(), "tests/collada"), VFS_MOUNT_MUST_EXIST));
TS_ASSERT_OK(g_VFS->Mount(L"collada/", DataDir()/"tests/collada", VFS_MOUNT_MUST_EXIST));
// Mount _testcache onto virtual /cache - don't use the normal cache
// directory because that's full of loads of cached files from the
@ -126,7 +127,7 @@ public:
CModelDefPtr modeldef = meshManager->GetMesh(testPMD);
TS_ASSERT(modeldef);
if (modeldef) TS_ASSERT_WSTR_EQUALS(modeldef->GetName(), testBase);
if (modeldef) TS_ASSERT_PATH_EQUALS(modeldef->GetName(), testBase);
}
void test_load_pmd_without_extension()
@ -135,7 +136,7 @@ public:
CModelDefPtr modeldef = meshManager->GetMesh(testBase);
TS_ASSERT(modeldef);
if (modeldef) TS_ASSERT_WSTR_EQUALS(modeldef->GetName(), testBase);
if (modeldef) TS_ASSERT_PATH_EQUALS(modeldef->GetName(), testBase);
}
void test_caching()
@ -155,7 +156,7 @@ public:
CModelDefPtr modeldef = meshManager->GetMesh(testDAE);
TS_ASSERT(modeldef);
if (modeldef) TS_ASSERT_WSTR_EQUALS(modeldef->GetName(), testBase);
if (modeldef) TS_ASSERT_PATH_EQUALS(modeldef->GetName(), testBase);
}
void test_load_dae_caching()
@ -166,7 +167,7 @@ public:
VfsPath daeName1 = colladaManager->GetLoadableFilename(testBase, CColladaManager::PMD);
VfsPath daeName2 = colladaManager->GetLoadableFilename(testBase, CColladaManager::PMD);
TS_ASSERT(!daeName1.empty());
TS_ASSERT_WSTR_EQUALS(daeName1, daeName2);
TS_ASSERT_PATH_EQUALS(daeName1, daeName2);
// TODO: it'd be nice to test that it really isn't doing the DAE->PMD
// conversion a second time, but there doesn't seem to be an easy way
// to check that
@ -229,7 +230,7 @@ public:
copyFile(srcSkeletonDefs, testSkeletonDefs);
CModelDefPtr modeldef = meshManager->GetMesh(testDAE);
TS_ASSERT(modeldef);
if (modeldef) TS_ASSERT_WSTR_EQUALS(modeldef->GetName(), testBase);
if (modeldef) TS_ASSERT_PATH_EQUALS(modeldef->GetName(), testBase);
TS_ASSERT(v.Validate(L"doc", L"<test>2.0</test>"));
}

View File

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

View File

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

View File

@ -1083,7 +1083,7 @@ void CGUI::LoadXmlFile(const VfsPath& Filename, boost::unordered_set<VfsPath>& P
}
catch (PSERROR_GUI& e)
{
LOGERROR(L"Errors loading GUI file %ls (%d)", Filename.c_str(), e.getCode());
LOGERROR(L"Errors loading GUI file %ls (%d)", Filename.string().c_str(), e.getCode());
return;
}
}
@ -1578,7 +1578,7 @@ void CGUI::Xeromyces_ReadImage(XMBElement Element, CXeromyces* pFile, CGUISprite
if (attr_name == "texture")
{
image.m_TextureName = Path::Join("art/textures/ui", attr_value);
image.m_TextureName = VfsPath("art/textures/ui") / attr_value;
}
else
if (attr_name == "size")

View File

@ -115,7 +115,7 @@ void CGUIManager::LoadPage(SGUIPage& page)
page.gui.reset(new CGUI());
page.gui->Initialize();
VfsPath path = Path::Join("gui", VfsPath(page.name.c_str()));
VfsPath path = VfsPath("gui") / page.name;
page.inputs.insert(path);
CXeromyces xero;
@ -144,7 +144,7 @@ void CGUIManager::LoadPage(SGUIPage& page)
CStrW name (node.GetText().FromUTF8());
TIMER(name.c_str());
VfsPath path = Path::Join("gui", VfsPath(name.c_str()));
VfsPath path = VfsPath("gui") / name;
page.gui->LoadXmlFile(path, page.inputs);
}
@ -169,7 +169,7 @@ LibError CGUIManager::ReloadChangedFiles(const VfsPath& path)
{
if (it->inputs.count(path))
{
LOGMESSAGE(L"GUI file '%ls' changed - reloading page '%ls'", path.c_str(), it->name.c_str());
LOGMESSAGE(L"GUI file '%ls' changed - reloading page '%ls'", path.string().c_str(), it->name.c_str());
LoadPage(*it);
// TODO: this can crash if LoadPage runs an init script which modifies the page stack and breaks our iterators
}

View File

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

View File

@ -312,7 +312,7 @@ CScriptVal LoadMapSettings(void* cbdata, VfsPath pathname)
CMapSummaryReader reader;
if (reader.LoadMap(VfsPath(pathname + L".xml")) != PSRETURN_OK)
if (reader.LoadMap(pathname.ChangeExtension(L".xml")) != PSRETURN_OK)
return CScriptVal();
return reader.GetMapSettings(guiManager->GetScriptInterface()).get();
@ -433,8 +433,8 @@ void ForceGC(void* cbdata)
void DumpSimState(void* UNUSED(cbdata))
{
NativePath path = Path::Join(psLogDir(), "sim_dump.txt");
std::ofstream file (StringFromNativePath(path).c_str(), std::ofstream::out | std::ofstream::trunc);
OsPath path = psLogDir()/"sim_dump.txt";
std::ofstream file (OsString(path).c_str(), std::ofstream::out | std::ofstream::trunc);
g_Game->GetSimulation2()->DumpDebugState(file);
}

View File

@ -41,14 +41,14 @@ static void def_override_gl_upload_caps()
}
static const NativePath& def_get_log_dir()
static const OsPath& def_get_log_dir()
{
static NativePath logDir;
static OsPath logDir;
if(logDir.empty())
{
NativePath exePathname;
OsPath exePathname;
(void)sys_get_executable_name(exePathname);
logDir = Path::Path(exePathname);
logDir = exePathname.Parent();
}
return logDir;
}
@ -153,7 +153,7 @@ void ah_override_gl_upload_caps()
ah.override_gl_upload_caps();
}
const NativePath& ah_get_log_dir()
const OsPath& ah_get_log_dir()
{
return ah.get_log_dir();
}

View File

@ -117,7 +117,7 @@ extern void ah_override_gl_upload_caps();
*
* @return path ending with directory separator (e.g. '/').
**/
extern const NativePath& ah_get_log_dir();
extern const OsPath& ah_get_log_dir();
/**
* gather all app-related logs/information and write it to file.
@ -179,7 +179,7 @@ extern ErrorReactionInternal ah_display_error(const wchar_t* text, size_t flags)
struct AppHooks
{
void (*override_gl_upload_caps)();
const NativePath& (*get_log_dir)();
const OsPath& (*get_log_dir)();
void (*bundle_logs)(FILE* f);
const wchar_t* (*translate)(const wchar_t* text);
void (*translate_free)(const wchar_t* text);

View File

@ -173,10 +173,9 @@ LibError debug_WriteCrashlog(const wchar_t* text)
if(!cpu_CAS(&state, IDLE, BUSY))
return ERR::REENTERED; // NOWARN
FILE* f;
NativePath pathname = Path::Join(ah_get_log_dir(), "crashlog.txt");
errno_t err = _wfopen_s(&f, pathname.c_str(), L"w");
if(err != 0)
OsPath pathname = ah_get_log_dir()/"crashlog.txt";
FILE* f = sys_OpenFile(pathname, "w");
if(!f)
{
state = FAILED; // must come before DEBUG_DISPLAY_ERROR
DEBUG_DISPLAY_ERROR(L"Unable to open crashlog.txt for writing (please ensure the log directory is writable)");

View File

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

View File

@ -91,7 +91,7 @@ struct IArchiveWriter
* @param pathname the actual file to add
* @param pathnameInArchive the name to store in the archive
**/
virtual LibError AddFile(const NativePath& pathname, const NativePath& pathameInArchive) = 0;
virtual LibError AddFile(const OsPath& pathname, const Path& pathameInArchive) = 0;
};
typedef shared_ptr<IArchiveWriter> PIArchiveWriter;

View File

@ -34,8 +34,8 @@
#include "lib/bits.h"
#include "lib/byte_order.h"
#include "lib/fat_time.h"
#include "lib/path_util.h"
#include "lib/allocators/pool.h"
#include "lib/sysdep/filesystem.h"
#include "lib/file/archive/archive.h"
#include "lib/file/archive/codec_zlib.h"
#include "lib/file/archive/stream.h"
@ -64,9 +64,9 @@ enum ZipMethod
class LFH
{
public:
void Init(const FileInfo& fileInfo, off_t csize, ZipMethod method, u32 checksum, const NativePath& pathname)
void Init(const FileInfo& fileInfo, off_t csize, ZipMethod method, u32 checksum, const Path& pathname)
{
const std::string pathnameUTF8 = utf8_from_wstring(pathname);
const std::string pathnameUTF8 = utf8_from_wstring(pathname.string());
const size_t pathnameSize = pathnameUTF8.length();
m_magic = lfh_magic;
@ -112,9 +112,9 @@ cassert(sizeof(LFH) == 30);
class CDFH
{
public:
void Init(const FileInfo& fileInfo, off_t ofs, off_t csize, ZipMethod method, u32 checksum, const NativePath& pathname, size_t slack)
void Init(const FileInfo& fileInfo, off_t ofs, off_t csize, ZipMethod method, u32 checksum, const Path& pathname, size_t slack)
{
const std::string pathnameUTF8 = utf8_from_wstring(pathname);
const std::string pathnameUTF8 = utf8_from_wstring(pathname.string());
const size_t pathnameLength = pathnameUTF8.length();
m_magic = cdfh_magic;
@ -135,11 +135,11 @@ public:
memcpy((char*)this + sizeof(CDFH), pathnameUTF8.c_str(), pathnameLength);
}
NativePath Pathname() const
Path Pathname() const
{
const size_t length = (size_t)read_le16(&m_fn_len);
const char* pathname = (const char*)this + sizeof(CDFH); // not 0-terminated!
return NativePathFromString(std::string(pathname, length));
return Path(std::string(pathname, length));
}
off_t HeaderOffset() const
@ -264,12 +264,12 @@ public:
return 'A';
}
virtual NativePath Path() const
virtual OsPath Path() const
{
return m_file->Pathname();
}
virtual LibError Load(const NativePath& UNUSED(name), const shared_ptr<u8>& buf, size_t size) const
virtual LibError Load(const OsPath& UNUSED(name), const shared_ptr<u8>& buf, size_t size) const
{
AdjustOffset();
@ -381,7 +381,7 @@ private:
class ArchiveReader_Zip : public IArchiveReader
{
public:
ArchiveReader_Zip(const NativePath& pathname)
ArchiveReader_Zip(const OsPath& pathname)
: m_file(new File(pathname, 'r'))
{
FileInfo fileInfo;
@ -411,10 +411,10 @@ public:
if(!cdfh)
WARN_RETURN(ERR::CORRUPTED);
const VfsPath relativePathname(cdfh->Pathname());
if(!Path::IsDirectory(relativePathname))
const Path relativePathname(cdfh->Pathname());
if(!relativePathname.IsDirectory())
{
const NativePath name = Path::Filename(relativePathname);
const OsPath name = relativePathname.Filename();
FileInfo fileInfo(name, cdfh->USize(), cdfh->MTime());
shared_ptr<ArchiveFile_Zip> archiveFile(new ArchiveFile_Zip(m_file, cdfh->HeaderOffset(), cdfh->CSize(), cdfh->Checksum(), cdfh->Method()));
cb(relativePathname, fileInfo, archiveFile, cbData);
@ -514,7 +514,7 @@ private:
off_t m_fileSize;
};
PIArchiveReader CreateArchiveReader_Zip(const NativePath& archivePathname)
PIArchiveReader CreateArchiveReader_Zip(const OsPath& archivePathname)
{
return PIArchiveReader(new ArchiveReader_Zip(archivePathname));
}
@ -527,7 +527,7 @@ PIArchiveReader CreateArchiveReader_Zip(const NativePath& archivePathname)
class ArchiveWriter_Zip : public IArchiveWriter
{
public:
ArchiveWriter_Zip(const NativePath& archivePathname, bool noDeflate)
ArchiveWriter_Zip(const OsPath& archivePathname, bool noDeflate)
: m_file(new File(archivePathname, 'w')), m_fileSize(0)
, m_unalignedWriter(new UnalignedWriter(m_file, 0))
, m_numEntries(0), m_noDeflate(noDeflate)
@ -552,16 +552,16 @@ public:
(void)pool_destroy(&m_cdfhPool);
const NativePath pathname = m_file->Pathname(); // (must be retrieved before resetting m_file)
const OsPath pathname = m_file->Pathname(); // (must be retrieved before resetting m_file)
m_file.reset();
m_fileSize += off_t(cd_size+sizeof(ECDR));
// remove padding added by UnalignedWriter
wtruncate(pathname.c_str(), m_fileSize);
wtruncate(pathname, m_fileSize);
}
LibError AddFile(const NativePath& pathname, const NativePath& pathnameInArchive)
LibError AddFile(const OsPath& pathname, const OsPath& pathnameInArchive)
{
FileInfo fileInfo;
RETURN_ERR(GetFileInfo(pathname, &fileInfo));
@ -580,7 +580,7 @@ public:
PFile file(new File);
RETURN_ERR(file->Open(pathname, 'r'));
const size_t pathnameLength = pathnameInArchive.length();
const size_t pathnameLength = pathnameInArchive.string().length();
// choose method and the corresponding codec
ZipMethod method;
@ -638,9 +638,9 @@ public:
}
private:
static bool IsFileTypeIncompressible(const NativePath& pathname)
static bool IsFileTypeIncompressible(const OsPath& pathname)
{
const NativePath extension = Path::Extension(pathname);
const OsPath extension = pathname.Extension();
// file extensions that we don't want to compress
static const wchar_t* incompressibleExtensions[] =
@ -652,7 +652,7 @@ private:
for(size_t i = 0; i < ARRAY_SIZE(incompressibleExtensions); i++)
{
if(!wcscasecmp(extension.c_str(), incompressibleExtensions[i]))
if(extension == incompressibleExtensions[i])
return true;
}
@ -669,7 +669,7 @@ private:
bool m_noDeflate;
};
PIArchiveWriter CreateArchiveWriter_Zip(const NativePath& archivePathname, bool noDeflate)
PIArchiveWriter CreateArchiveWriter_Zip(const OsPath& archivePathname, bool noDeflate)
{
return PIArchiveWriter(new ArchiveWriter_Zip(archivePathname, noDeflate));
}

View File

@ -29,7 +29,7 @@
#include "lib/file/archive/archive.h"
LIB_API PIArchiveReader CreateArchiveReader_Zip(const NativePath& archivePathname);
LIB_API PIArchiveWriter CreateArchiveWriter_Zip(const NativePath& archivePathname, bool noDeflate);
LIB_API PIArchiveReader CreateArchiveReader_Zip(const OsPath& archivePathname);
LIB_API PIArchiveWriter CreateArchiveWriter_Zip(const OsPath& archivePathname, bool noDeflate);
#endif // #ifndef INCLUDED_ARCHIVE_ZIP

View File

@ -31,9 +31,9 @@ struct IFileLoader
virtual size_t Precedence() const = 0;
virtual wchar_t LocationCode() const = 0;
virtual NativePath Path() const = 0;
virtual OsPath Path() const = 0;
virtual LibError Load(const NativePath& name, const shared_ptr<u8>& buf, size_t size) const = 0;
virtual LibError Load(const OsPath& name, const shared_ptr<u8>& buf, size_t size) const = 0;
};
typedef shared_ptr<IFileLoader> PIFileLoader;

View File

@ -23,12 +23,12 @@
#include "precompiled.h"
#include "lib/file/common/real_directory.h"
#include "lib/path_util.h"
#include "lib/sysdep/filesystem.h"
#include "lib/file/file.h"
#include "lib/file/io/io.h"
RealDirectory::RealDirectory(const NativePath& path, size_t priority, size_t flags)
RealDirectory::RealDirectory(const OsPath& path, size_t priority, size_t flags)
: m_path(path), m_priority(priority), m_flags(flags)
{
}
@ -46,9 +46,9 @@ RealDirectory::RealDirectory(const NativePath& path, size_t priority, size_t fla
}
/*virtual*/ LibError RealDirectory::Load(const NativePath& name, const shared_ptr<u8>& buf, size_t size) const
/*virtual*/ LibError RealDirectory::Load(const OsPath& name, const shared_ptr<u8>& buf, size_t size) const
{
const NativePath pathname = Path::Join(m_path, name);
const OsPath pathname = m_path / name;
PFile file(new File);
RETURN_ERR(file->Open(pathname, 'r'));
@ -58,9 +58,9 @@ RealDirectory::RealDirectory(const NativePath& path, size_t priority, size_t fla
}
LibError RealDirectory::Store(const NativePath& name, const shared_ptr<u8>& fileContents, size_t size)
LibError RealDirectory::Store(const OsPath& name, const shared_ptr<u8>& fileContents, size_t size)
{
const NativePath pathname = Path::Join(m_path, name);
const OsPath pathname = m_path / name;
{
PFile file(new File);
@ -72,7 +72,7 @@ LibError RealDirectory::Store(const NativePath& name, const shared_ptr<u8>& file
// length. ftruncate can't be used because Windows' FILE_FLAG_NO_BUFFERING
// only allows resizing to sector boundaries, so the file must first
// be closed.
wtruncate(pathname.c_str(), size);
wtruncate(pathname, size);
return INFO::OK;
}
@ -85,8 +85,8 @@ void RealDirectory::Watch()
}
PRealDirectory CreateRealSubdirectory(const PRealDirectory& realDirectory, const NativePath& subdirectoryName)
PRealDirectory CreateRealSubdirectory(const PRealDirectory& realDirectory, const OsPath& subdirectoryName)
{
const NativePath path = Path::AddSlash(Path::Join(realDirectory->Path(), subdirectoryName));
const OsPath path = realDirectory->Path() / subdirectoryName/"";
return PRealDirectory(new RealDirectory(path, realDirectory->Priority(), realDirectory->Flags()));
}

View File

@ -30,7 +30,7 @@ class RealDirectory : public IFileLoader
{
NONCOPYABLE(RealDirectory);
public:
RealDirectory(const NativePath& path, size_t priority, size_t flags);
RealDirectory(const OsPath& path, size_t priority, size_t flags);
size_t Priority() const
{
@ -45,13 +45,13 @@ public:
// IFileLoader
virtual size_t Precedence() const;
virtual wchar_t LocationCode() const;
virtual NativePath Path() const
virtual OsPath Path() const
{
return m_path;
}
virtual LibError Load(const NativePath& name, const shared_ptr<u8>& buf, size_t size) const;
virtual LibError Load(const OsPath& name, const shared_ptr<u8>& buf, size_t size) const;
LibError Store(const NativePath& name, const shared_ptr<u8>& fileContents, size_t size);
LibError Store(const OsPath& name, const shared_ptr<u8>& fileContents, size_t size);
void Watch();
@ -59,7 +59,7 @@ private:
// note: paths are relative to the root directory, so storing the
// entire path instead of just the portion relative to the mount point
// is not all too wasteful.
const NativePath m_path;
const OsPath m_path;
const size_t m_priority;
@ -72,6 +72,6 @@ private:
typedef shared_ptr<RealDirectory> PRealDirectory;
extern PRealDirectory CreateRealSubdirectory(const PRealDirectory& realDirectory, const NativePath& subdirectoryName);
extern PRealDirectory CreateRealSubdirectory(const PRealDirectory& realDirectory, const OsPath& subdirectoryName);
#endif // #ifndef INCLUDED_REAL_DIRECTORY

View File

@ -34,7 +34,7 @@ public:
TraceEntry t1(TraceEntry::Load, L"example.txt", 1234);
TS_ASSERT_EQUALS(t1.Action(), TraceEntry::Load);
TS_ASSERT_WSTR_EQUALS(t1.Pathname(), L"example.txt");
TS_ASSERT_PATH_EQUALS(t1.Pathname(), OsPath(L"example.txt"));
TS_ASSERT_EQUALS(t1.Size(), (size_t)1234);
buf1 = t1.EncodeAsText();
@ -44,7 +44,7 @@ public:
TraceEntry t2(TraceEntry::Store, L"example two.txt", 16777216);
TS_ASSERT_EQUALS(t2.Action(), TraceEntry::Store);
TS_ASSERT_WSTR_EQUALS(t2.Pathname(), L"example two.txt");
TS_ASSERT_PATH_EQUALS(t2.Pathname(), OsPath(L"example two.txt"));
TS_ASSERT_EQUALS(t2.Size(), (size_t)16777216);
buf2 = t2.EncodeAsText();
@ -52,20 +52,20 @@ public:
TraceEntry t3(buf1);
TS_ASSERT_EQUALS(t3.Action(), TraceEntry::Load);
TS_ASSERT_WSTR_EQUALS(t3.Pathname(), L"example.txt");
TS_ASSERT_PATH_EQUALS(t3.Pathname(), OsPath(L"example.txt"));
TS_ASSERT_EQUALS(t3.Size(), (size_t)1234);
TraceEntry t4(buf2);
TS_ASSERT_EQUALS(t4.Action(), TraceEntry::Store);
TS_ASSERT_WSTR_EQUALS(t4.Pathname(), L"example two.txt");
TS_ASSERT_PATH_EQUALS(t4.Pathname(), OsPath(L"example two.txt"));
TS_ASSERT_EQUALS(t4.Size(), (size_t)16777216);
}
void test_maxpath()
{
NativePath path1(PATH_MAX, L'x');
std::wstring buf1 = L"0: L \"" + path1 + L"\" 0\n";
OsPath path1(std::wstring(PATH_MAX, L'x'));
std::wstring buf1 = L"0: L \"" + path1.string() + L"\" 0\n";
TraceEntry t1(buf1);
TS_ASSERT_WSTR_EQUALS(t1.Pathname(), path1);
TS_ASSERT_PATH_EQUALS(t1.Pathname(), path1);
}
};

View File

@ -33,7 +33,7 @@
#include "lib/allocators/pool.h"
#include "lib/bits.h" // round_up
#include "lib/timer.h" // timer_Time
#include "lib/path_util.h"
#include "lib/sysdep/sysdep.h" // sys_OpenFile
/*virtual*/ ITrace::~ITrace()
@ -44,7 +44,7 @@
//-----------------------------------------------------------------------------
TraceEntry::TraceEntry(EAction action, const NativePath& pathname, size_t size)
TraceEntry::TraceEntry(EAction action, const Path& pathname, size_t size)
: m_timestamp((float)timer_Time())
, m_action(action)
, m_pathname(pathname)
@ -74,9 +74,9 @@ TraceEntry::TraceEntry(const std::wstring& text)
stream >> dummy;
debug_assert(dummy == '"');
NativePath pathname;
Path::String pathname;
std::getline(stream, pathname, L'"');
m_pathname = pathname;
m_pathname = Path(pathname);
stream >> m_size;
@ -90,7 +90,7 @@ std::wstring TraceEntry::EncodeAsText() const
{
const wchar_t action = (wchar_t)m_action;
wchar_t buf[1000];
swprintf_s(buf, ARRAY_SIZE(buf), L"%#010f: %c \"%ls\" %lu\n", m_timestamp, action, m_pathname.c_str(), (unsigned long)m_size);
swprintf_s(buf, ARRAY_SIZE(buf), L"%#010f: %c \"%ls\" %lu\n", m_timestamp, action, m_pathname.string().c_str(), (unsigned long)m_size);
return buf;
}
@ -105,20 +105,20 @@ public:
}
virtual void NotifyLoad(const NativePath& UNUSED(pathname), size_t UNUSED(size))
virtual void NotifyLoad(const Path& UNUSED(pathname), size_t UNUSED(size))
{
}
virtual void NotifyStore(const NativePath& UNUSED(pathname), size_t UNUSED(size))
virtual void NotifyStore(const Path& UNUSED(pathname), size_t UNUSED(size))
{
}
virtual LibError Load(const NativePath& UNUSED(pathname))
virtual LibError Load(const OsPath& UNUSED(pathname))
{
return INFO::OK;
}
virtual LibError Store(const NativePath& UNUSED(pathname)) const
virtual LibError Store(const OsPath& UNUSED(pathname)) const
{
return INFO::OK;
}
@ -156,24 +156,23 @@ public:
(void)pool_destroy(&m_pool);
}
virtual void NotifyLoad(const NativePath& pathname, size_t size)
virtual void NotifyLoad(const Path& pathname, size_t size)
{
new(Allocate()) TraceEntry(TraceEntry::Load, pathname, size);
}
virtual void NotifyStore(const NativePath& pathname, size_t size)
virtual void NotifyStore(const Path& pathname, size_t size)
{
new(Allocate()) TraceEntry(TraceEntry::Store, pathname, size);
}
virtual LibError Load(const NativePath& pathname)
virtual LibError Load(const OsPath& pathname)
{
pool_free_all(&m_pool);
errno = 0;
FILE* file;
errno_t err = _wfopen_s(&file, pathname.c_str(), L"rt");
if(err != 0)
FILE* file = sys_OpenFile(pathname, "rt");
if(!file)
return LibError_from_errno();
for(;;)
@ -188,12 +187,11 @@ public:
return INFO::OK;
}
virtual LibError Store(const NativePath& pathname) const
virtual LibError Store(const OsPath& pathname) const
{
errno = 0;
FILE* file;
errno_t err = _wfopen_s(&file, pathname.c_str(), L"at");
if(err != 0)
FILE* file = sys_OpenFile(pathname, "at");
if(!file)
return LibError_from_errno();
for(size_t i = 0; i < NumEntries(); i++)
{

View File

@ -47,7 +47,7 @@ public:
Store = 'S'
};
TraceEntry(EAction action, const NativePath& pathname, size_t size);
TraceEntry(EAction action, const Path& pathname, size_t size);
TraceEntry(const std::wstring& text);
EAction Action() const
@ -55,7 +55,7 @@ public:
return m_action;
}
const NativePath& Pathname() const
const Path& Pathname() const
{
return m_pathname;
}
@ -78,7 +78,7 @@ private:
EAction m_action;
NativePath m_pathname;
Path m_pathname;
// size of file.
// rationale: other applications using this trace format might not
@ -93,8 +93,8 @@ struct ITrace
{
virtual ~ITrace();
virtual void NotifyLoad(const NativePath& pathname, size_t size) = 0;
virtual void NotifyStore(const NativePath& pathname, size_t size) = 0;
virtual void NotifyLoad(const Path& pathname, size_t size) = 0;
virtual void NotifyStore(const Path& pathname, size_t size) = 0;
/**
* store all entries into a file.
@ -105,7 +105,7 @@ struct ITrace
* because storing filename strings in a binary format would be a
* bit awkward.
**/
virtual LibError Store(const NativePath& pathname) const = 0;
virtual LibError Store(const OsPath& pathname) const = 0;
/**
* load entries from file.
@ -114,7 +114,7 @@ struct ITrace
*
* replaces any existing entries.
**/
virtual LibError Load(const NativePath& osPathname) = 0;
virtual LibError Load(const OsPath& pathname) = 0;
virtual const TraceEntry* Entries() const = 0;
virtual size_t NumEntries() const = 0;

View File

@ -38,7 +38,7 @@ ERROR_ASSOCIATE(ERR::IO, L"Error during IO", EIO);
namespace FileImpl {
LibError Open(const NativePath& pathname, wchar_t accessType, int& fd)
LibError Open(const OsPath& pathname, wchar_t accessType, int& fd)
{
int oflag = 0;
switch(accessType)
@ -61,7 +61,7 @@ LibError Open(const NativePath& pathname, wchar_t accessType, int& fd)
// prevent exploits by disallowing writes to our files by other users.
// note that the system-wide installed cache is read-only.
const mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH; // 0644
fd = wopen(pathname.c_str(), oflag, mode);
fd = wopen(pathname, oflag, mode);
if(fd < 0)
return LibError_from_errno(false);

View File

@ -39,7 +39,7 @@ namespace ERR
namespace FileImpl
{
LIB_API LibError Open(const NativePath& pathname, wchar_t mode, int& fd);
LIB_API LibError Open(const OsPath& pathname, wchar_t mode, int& fd);
LIB_API void Close(int& fd);
LIB_API LibError IO(int fd, wchar_t mode, off_t ofs, u8* buf, size_t size);
LIB_API LibError Issue(aiocb& req, int fd, wchar_t mode, off_t alignedOfs, u8* alignedBuf, size_t alignedSize);
@ -55,7 +55,7 @@ public:
{
}
LibError Open(const NativePath& pathname, wchar_t mode)
LibError Open(const OsPath& pathname, wchar_t mode)
{
RETURN_ERR(FileImpl::Open(pathname, mode, m_fd));
m_pathname = pathname;
@ -68,7 +68,7 @@ public:
FileImpl::Close(m_fd);
}
File(const NativePath& pathname, wchar_t mode)
File(const OsPath& pathname, wchar_t mode)
{
(void)Open(pathname, mode);
}
@ -78,7 +78,7 @@ public:
Close();
}
const NativePath& Pathname() const
const OsPath& Pathname() const
{
return m_pathname;
}
@ -104,7 +104,7 @@ public:
}
private:
NativePath m_pathname;
OsPath m_pathname;
int m_fd;
wchar_t m_mode;
};

View File

@ -40,19 +40,11 @@ struct DirDeleter
}
};
// is name "." or ".."?
static bool IsDummyDirectory(const NativePath& name)
{
if(name[0] != '.')
return false;
return (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'));
}
LibError GetDirectoryEntries(const NativePath& path, FileInfos* files, DirectoryNames* subdirectoryNames)
LibError GetDirectoryEntries(const OsPath& path, FileInfos* files, DirectoryNames* subdirectoryNames)
{
// open directory
errno = 0;
WDIR* pDir = wopendir(path.c_str());
WDIR* pDir = wopendir(path);
if(!pDir)
return LibError_from_errno(false);
shared_ptr<WDIR> osDir(pDir, DirDeleter());
@ -69,8 +61,8 @@ LibError GetDirectoryEntries(const NativePath& path, FileInfos* files, Directory
return LibError_from_errno();
}
const NativePath name(osEnt->d_name);
RETURN_ERR(path_component_validate(name.c_str()));
const OsPath name(osEnt->d_name);
RETURN_ERR(name.Validate());
// get file information (mode, size, mtime)
struct stat s;
@ -80,39 +72,39 @@ LibError GetDirectoryEntries(const NativePath& path, FileInfos* files, Directory
#else
// .. call regular stat().
errno = 0;
const NativePath pathname = Path::Join(path, name);
if(wstat(pathname.c_str(), &s) != 0)
const OsPath pathname = path / name;
if(wstat(pathname, &s) != 0)
return LibError_from_errno();
#endif
if(files && S_ISREG(s.st_mode))
files->push_back(FileInfo(name, s.st_size, s.st_mtime));
else if(subdirectoryNames && S_ISDIR(s.st_mode) && !IsDummyDirectory(name))
else if(subdirectoryNames && S_ISDIR(s.st_mode) && name != L"." && name != L"..")
subdirectoryNames->push_back(name);
}
}
LibError GetFileInfo(const NativePath& pathname, FileInfo* pfileInfo)
LibError GetFileInfo(const OsPath& pathname, FileInfo* pfileInfo)
{
errno = 0;
struct stat s;
memset(&s, 0, sizeof(s));
if(wstat(pathname.c_str(), &s) != 0)
if(wstat(pathname, &s) != 0)
return LibError_from_errno();
*pfileInfo = FileInfo(Path::Filename(pathname), s.st_size, s.st_mtime);
*pfileInfo = FileInfo(pathname.Filename(), s.st_size, s.st_mtime);
return INFO::OK;
}
LibError CreateDirectories(const NativePath& path, mode_t mode)
LibError CreateDirectories(const OsPath& path, mode_t mode)
{
if(path.empty())
return INFO::OK;
struct stat s;
if(wstat(path.c_str(), &s) == 0)
if(wstat(path, &s) == 0)
{
if(!S_ISDIR(s.st_mode)) // encountered a file
WARN_RETURN(ERR::FAIL);
@ -120,21 +112,21 @@ LibError CreateDirectories(const NativePath& path, mode_t mode)
}
// If we were passed a path ending with '/', strip the '/' now so that
// we can consistently use Path to find parent directory names
if(Path::IsDirectory(path))
return CreateDirectories(Path::Path(path), mode);
// we can consistently use Parent to find parent directory names
if(path.IsDirectory())
return CreateDirectories(path.Parent(), mode);
RETURN_ERR(CreateDirectories(Path::Path(path), mode));
RETURN_ERR(CreateDirectories(path.Parent(), mode));
errno = 0;
if(wmkdir(path.c_str(), mode) != 0)
if(wmkdir(path, mode) != 0)
return LibError_from_errno();
return INFO::OK;
}
LibError DeleteDirectory(const NativePath& path)
LibError DeleteDirectory(const OsPath& path)
{
// note: we have to recursively empty the directory before it can
// be deleted (required by Windows and POSIX rmdir()).
@ -145,18 +137,18 @@ LibError DeleteDirectory(const NativePath& path)
// delete files
for(size_t i = 0; i < files.size(); i++)
{
const NativePath pathname = Path::Join(path, files[i].Name());
const OsPath pathname = path / files[i].Name();
errno = 0;
if(wunlink(pathname.c_str()) != 0)
if(wunlink(pathname) != 0)
return LibError_from_errno();
}
// recurse over subdirectoryNames
for(size_t i = 0; i < subdirectoryNames.size(); i++)
RETURN_ERR(DeleteDirectory(Path::Join(path, subdirectoryNames[i])));
RETURN_ERR(DeleteDirectory(path / subdirectoryNames[i]));
errno = 0;
if(wrmdir(path.c_str()) != 0)
if(wrmdir(path) != 0)
return LibError_from_errno();
return INFO::OK;

View File

@ -34,12 +34,12 @@ public:
{
}
FileInfo(const NativePath& name, off_t size, time_t mtime)
FileInfo(const OsPath& name, off_t size, time_t mtime)
: name(name), size(size), mtime(mtime)
{
}
const NativePath& Name() const
const OsPath& Name() const
{
return name;
}
@ -55,22 +55,22 @@ public:
}
private:
NativePath name;
OsPath name;
off_t size;
time_t mtime;
};
extern LibError GetFileInfo(const NativePath& pathname, FileInfo* fileInfo);
extern LibError GetFileInfo(const OsPath& pathname, FileInfo* fileInfo);
typedef std::vector<FileInfo> FileInfos;
typedef std::vector<NativePath> DirectoryNames;
typedef std::vector<OsPath> DirectoryNames;
extern LibError GetDirectoryEntries(const NativePath& path, FileInfos* files, DirectoryNames* subdirectoryNames);
extern LibError GetDirectoryEntries(const OsPath& path, FileInfos* files, DirectoryNames* subdirectoryNames);
// same as boost::filesystem::create_directories, except that mkdir is invoked with
// <mode> instead of 0755.
extern LibError CreateDirectories(const NativePath& path, mode_t mode);
extern LibError CreateDirectories(const OsPath& path, mode_t mode);
extern LibError DeleteDirectory(const NativePath& dirPath);
extern LibError DeleteDirectory(const OsPath& dirPath);
#endif // #ifndef INCLUDED_FILE_SYSTEM

View File

@ -31,12 +31,40 @@
#include <cstring>
#include <cstdio>
#include "lib/path_util.h"
#include "lib/sysdep/filesystem.h"
#include "lib/regex.h"
namespace fs_util {
bool DirectoryExists(const OsPath& path)
{
WDIR* dir = wopendir(path);
if(dir)
{
wclosedir(dir);
return true;
}
return false;
}
bool FileExists(const OsPath& pathname)
{
struct stat s;
const bool exists = wstat(pathname, &s) == 0;
return exists;
}
u64 FileSize(const OsPath& pathname)
{
struct stat s;
debug_assert(wstat(pathname, &s) == 0);
return s.st_size;
}
LibError GetPathnames(const PIVFS& fs, const VfsPath& path, const wchar_t* filter, VfsPaths& pathnames)
{
std::vector<FileInfo> files;
@ -47,42 +75,14 @@ LibError GetPathnames(const PIVFS& fs, const VfsPath& path, const wchar_t* filte
for(size_t i = 0; i < files.size(); i++)
{
if(match_wildcard(files[i].Name().c_str(), filter))
pathnames.push_back(Path::Join(path, files[i].Name()));
if(match_wildcard(files[i].Name().string().c_str(), filter))
pathnames.push_back(path / files[i].Name());
}
return INFO::OK;
}
struct FileInfoNameLess : public std::binary_function<const FileInfo, const FileInfo, bool>
{
bool operator()(const FileInfo& fileInfo1, const FileInfo& fileInfo2) const
{
return wcscasecmp(fileInfo1.Name().c_str(), fileInfo2.Name().c_str()) < 0;
}
};
void SortFiles(FileInfos& files)
{
std::sort(files.begin(), files.end(), FileInfoNameLess());
}
struct NameLess : public std::binary_function<const NativePath, const NativePath, bool>
{
bool operator()(const NativePath& name1, const NativePath& name2) const
{
return wcscasecmp(name1.c_str(), name2.c_str()) < 0;
}
};
void SortDirectories(DirectoryNames& directories)
{
std::sort(directories.begin(), directories.end(), NameLess());
}
LibError ForEachFile(const PIVFS& fs, const VfsPath& startPath, FileCallback cb, uintptr_t cbData, const wchar_t* pattern, size_t flags)
{
// (declare here to avoid reallocations)
@ -91,7 +91,7 @@ LibError ForEachFile(const PIVFS& fs, const VfsPath& startPath, FileCallback cb,
// (a FIFO queue is more efficient than recursion because it uses less
// stack space and avoids seeks due to breadth-first traversal.)
std::queue<VfsPath> pendingDirectories;
pendingDirectories.push(Path::AddSlash(startPath));
pendingDirectories.push(startPath/"");
while(!pendingDirectories.empty())
{
const VfsPath& path = pendingDirectories.front();
@ -101,10 +101,10 @@ LibError ForEachFile(const PIVFS& fs, const VfsPath& startPath, FileCallback cb,
for(size_t i = 0; i < files.size(); i++)
{
const FileInfo fileInfo = files[i];
if(!match_wildcard(fileInfo.Name().c_str(), pattern))
if(!match_wildcard(fileInfo.Name().string().c_str(), pattern))
continue;
const VfsPath pathname(Path::Join(path, fileInfo.Name())); // (FileInfo only stores the name)
const VfsPath pathname(path / fileInfo.Name()); // (FileInfo only stores the name)
cb(pathname, fileInfo, cbData);
}
@ -112,15 +112,7 @@ LibError ForEachFile(const PIVFS& fs, const VfsPath& startPath, FileCallback cb,
break;
for(size_t i = 0; i < subdirectoryNames.size(); i++)
{
VfsPath pathname;
if(path == L"/") // special case for startPath == L""
pathname = Path::AddSlash(VfsPath(subdirectoryNames[i]));
else
pathname = Path::AddSlash(Path::Join(path, subdirectoryNames[i]));
pendingDirectories.push(pathname);
}
pendingDirectories.push(path / subdirectoryNames[i]/"");
pendingDirectories.pop();
}
@ -137,8 +129,8 @@ void NextNumberedFilename(const PIVFS& fs, const VfsPath& pathnameFormat, size_t
// add 3rd -> without this measure it would get number 1, not 3.
if(nextNumber == 0)
{
const NativePath nameFormat = Path::Filename(pathnameFormat);
const VfsPath path = Path::AddSlash(Path::Path(pathnameFormat));
const VfsPath nameFormat = pathnameFormat.Filename();
const VfsPath path = pathnameFormat.Parent()/"";
size_t maxNumber = 0;
FileInfos files;
@ -146,7 +138,7 @@ void NextNumberedFilename(const PIVFS& fs, const VfsPath& pathnameFormat, size_t
for(size_t i = 0; i < files.size(); i++)
{
int number;
if(swscanf_s(files[i].Name().c_str(), nameFormat.c_str(), &number) == 1)
if(swscanf_s(files[i].Name().string().c_str(), nameFormat.string().c_str(), &number) == 1)
maxNumber = std::max(size_t(number), maxNumber);
}
@ -161,7 +153,7 @@ void NextNumberedFilename(const PIVFS& fs, const VfsPath& pathnameFormat, size_t
do
{
wchar_t pathnameBuf[PATH_MAX];
swprintf_s(pathnameBuf, ARRAY_SIZE(pathnameBuf), pathnameFormat.c_str(), nextNumber++);
swprintf_s(pathnameBuf, ARRAY_SIZE(pathnameBuf), pathnameFormat.string().c_str(), nextNumber++);
nextPathname = pathnameBuf;
}
while(fs->GetFileInfo(nextPathname, 0) == INFO::OK);

View File

@ -27,16 +27,18 @@
#ifndef INCLUDED_FILE_SYSTEM_UTIL
#define INCLUDED_FILE_SYSTEM_UTIL
#include "lib/native_path.h"
#include "lib/file/vfs/vfs.h"
namespace fs_util {
extern void SortFiles(FileInfos& files);
extern void SortDirectories(DirectoryNames& directories);
extern bool DirectoryExists(const OsPath& path);
extern bool FileExists(const OsPath& pathname);
extern u64 FileSize(const OsPath& pathname);
extern LibError GetPathnames(const PIVFS& fs, const VfsPath& path, const wchar_t* filter, VfsPaths& pathnames);
/**
* called for files in a directory.
*

View File

@ -43,9 +43,10 @@ BlockId::BlockId()
{
}
BlockId::BlockId(const NativePath& pathname, off_t ofs)
BlockId::BlockId(const OsPath& pathname, off_t ofs)
{
m_id = fnv_hash64(pathname.c_str(), pathname.length()*sizeof(pathname[0]));
const Path::String& string = pathname.string();
m_id = fnv_hash64(string.c_str(), string.length()*sizeof(string[0]));
const size_t indexBits = 16;
m_id <<= indexBits;
const off_t blockIndex = off_t(ofs / BLOCK_SIZE);

View File

@ -36,7 +36,7 @@ class BlockId
{
public:
BlockId();
BlockId(const NativePath& pathname, off_t ofs);
BlockId(const OsPath& pathname, off_t ofs);
bool operator==(const BlockId& rhs) const;
bool operator!=(const BlockId& rhs) const;

View File

@ -216,7 +216,7 @@ public:
}
private:
typedef Cache< VfsPath, shared_ptr<u8> > CacheType;
typedef Cache<VfsPath, shared_ptr<u8> > CacheType;
CacheType m_cache;
PAllocator m_allocator;

View File

@ -24,7 +24,7 @@
#include "lib/file/vfs/vfs.h"
#include "lib/allocators/shared_ptr.h"
#include "lib/path_util.h"
#include "lib/file/file_system_util.h"
#include "lib/file/common/file_stats.h"
#include "lib/file/common/trace.h"
#include "lib/file/archive/archive.h"
@ -47,9 +47,9 @@ public:
{
}
virtual LibError Mount(const VfsPath& mountPoint, const NativePath& path, size_t flags /* = 0 */, size_t priority /* = 0 */)
virtual LibError Mount(const VfsPath& mountPoint, const OsPath& path, size_t flags /* = 0 */, size_t priority /* = 0 */)
{
if(!DirectoryExists(path))
if(!fs_util::DirectoryExists(path))
{
if(flags & VFS_MOUNT_MUST_EXIST)
return ERR::VFS_DIR_NOT_FOUND; // NOWARN
@ -119,7 +119,7 @@ public:
CHECK_ERR(vfs_Lookup(pathname, &m_rootDirectory, directory, 0, VFS_LOOKUP_ADD|VFS_LOOKUP_CREATE));
const PRealDirectory& realDirectory = directory->AssociatedDirectory();
const NativePath name = Path::Filename(pathname);
const OsPath name = pathname.Filename();
RETURN_ERR(realDirectory->Store(name, fileContents, size));
// wipe out any cached blocks. this is necessary to cover the (rare) case
@ -129,7 +129,7 @@ public:
const VfsFile file(name, size, time(0), realDirectory->Priority(), realDirectory);
directory->AddFile(file);
m_trace->NotifyStore(pathname.c_str(), size);
m_trace->NotifyStore(pathname, size);
return INFO::OK;
}
@ -163,7 +163,7 @@ public:
stats_io_user_request(size);
stats_cache(isCacheHit? CR_HIT : CR_MISS, size);
m_trace->NotifyLoad(pathname.c_str(), size);
m_trace->NotifyLoad(pathname, size);
return INFO::OK;
}
@ -176,20 +176,20 @@ public:
return textRepresentation;
}
virtual LibError GetRealPath(const VfsPath& pathname, NativePath& realPathname)
virtual LibError GetRealPath(const VfsPath& pathname, OsPath& realPathname)
{
VfsDirectory* directory; VfsFile* file;
CHECK_ERR(vfs_Lookup(pathname, &m_rootDirectory, directory, &file));
realPathname = Path::Join(file->Loader()->Path(), Path::Filename(pathname));
realPathname = file->Loader()->Path() / pathname.Filename();
return INFO::OK;
}
virtual LibError GetVirtualPath(const NativePath& realPathname, VfsPath& pathname)
virtual LibError GetVirtualPath(const OsPath& realPathname, VfsPath& pathname)
{
const NativePath realPath = Path::AddSlash(Path::Path(realPathname));
const OsPath realPath = realPathname.Parent()/"";
VfsPath path;
RETURN_ERR(FindRealPathR(realPath, m_rootDirectory, L"", path));
pathname = Path::Join(path, Path::Filename(realPathname));
pathname = path / realPathname.Filename();
return INFO::OK;
}
@ -199,7 +199,7 @@ public:
VfsDirectory* directory;
RETURN_ERR(vfs_Lookup(pathname, &m_rootDirectory, directory, 0));
const NativePath name = Path::Filename(pathname);
const OsPath name = pathname.Filename();
directory->Invalidate(name);
return INFO::OK;
@ -211,7 +211,7 @@ public:
}
private:
LibError FindRealPathR(const NativePath& realPath, const VfsDirectory& directory, const VfsPath& curPath, VfsPath& path)
LibError FindRealPathR(const OsPath& realPath, const VfsDirectory& directory, const VfsPath& curPath, VfsPath& path)
{
PRealDirectory realDirectory = directory.AssociatedDirectory();
if(realDirectory && realDirectory->Path() == realPath)
@ -223,9 +223,9 @@ private:
const VfsDirectory::VfsSubdirectories& subdirectories = directory.Subdirectories();
for(VfsDirectory::VfsSubdirectories::const_iterator it = subdirectories.begin(); it != subdirectories.end(); ++it)
{
const NativePath& subdirectoryName = it->first;
const OsPath& subdirectoryName = it->first;
const VfsDirectory& subdirectory = it->second;
LibError ret = FindRealPathR(realPath, subdirectory, Path::AddSlash(Path::Join(curPath, subdirectoryName)), path);
LibError ret = FindRealPathR(realPath, subdirectory, curPath / subdirectoryName/"", path);
if(ret == INFO::OK)
return INFO::OK;
}

View File

@ -79,7 +79,7 @@ struct IVFS
* if files with archive extensions are seen, their contents are added
* as well.
**/
virtual LibError Mount(const VfsPath& mountPoint, const NativePath& path, size_t flags = 0, size_t priority = 0) = 0;
virtual LibError Mount(const VfsPath& mountPoint, const OsPath& path, size_t flags = 0, size_t priority = 0) = 0;
/**
* Retrieve information about a file (similar to POSIX stat).
@ -151,7 +151,7 @@ struct IVFS
*
* this is useful for passing paths to external libraries.
**/
virtual LibError GetRealPath(const VfsPath& pathname, NativePath& realPathname) = 0;
virtual LibError GetRealPath(const VfsPath& pathname, OsPath& realPathname) = 0;
/**
* retrieve the VFS pathname that corresponds to a real file.
@ -162,7 +162,7 @@ struct IVFS
* number of directories; this could be accelerated by only checking
* directories below a mount point with a matching real path.
**/
virtual LibError GetVirtualPath(const NativePath& realPathname, VfsPath& pathname) = 0;
virtual LibError GetVirtualPath(const OsPath& realPathname, VfsPath& pathname) = 0;
/**
* indicate that a file has changed; remove its data from the cache and

View File

@ -29,7 +29,7 @@
#include "lib/external_libraries/suppress_boost_warnings.h"
#include "lib/path_util.h" // path_foreach_component
#include "lib/sysdep/filesystem.h"
#include "lib/file/vfs/vfs.h" // error codes
#include "lib/file/vfs/vfs_tree.h"
#include "lib/file/vfs/vfs_populate.h"
@ -37,11 +37,11 @@
#include "lib/timer.h"
static LibError CreateDirectory(const NativePath& path)
static LibError CreateDirectory(const OsPath& path)
{
{
const mode_t mode = S_IRWXU; // 0700 as prescribed by XDG basedir
const int ret = wmkdir(path.c_str(), mode);
const int ret = wmkdir(path, mode);
if(ret == 0) // success
return INFO::OK;
}
@ -55,7 +55,7 @@ static LibError CreateDirectory(const NativePath& path)
// but first ensure it's really a directory (otherwise, a
// file is "in the way" and needs to be deleted)
struct stat s;
const int ret = wstat(path.c_str(), &s);
const int ret = wstat(path, &s);
debug_assert(ret == 0); // (wmkdir said it existed)
debug_assert(S_ISDIR(s.st_mode));
return INFO::OK;
@ -96,10 +96,10 @@ LibError vfs_Lookup(const VfsPath& pathname, VfsDirectory* startDirectory, VfsDi
size_t pos = 0; // (needed outside of loop)
for(;;)
{
const size_t nextSlash = pathname.find_first_of('/', pos);
if(nextSlash == VfsPath::npos)
const size_t nextSlash = pathname.string().find_first_of('/', pos);
if(nextSlash == VfsPath::String::npos)
break;
const NativePath subdirectoryName = pathname.substr(pos, nextSlash-pos);
const VfsPath subdirectoryName = pathname.string().substr(pos, nextSlash-pos);
pos = nextSlash+1;
VfsDirectory* subdirectory = directory->GetSubdirectory(subdirectoryName);
@ -113,10 +113,10 @@ LibError vfs_Lookup(const VfsPath& pathname, VfsDirectory* startDirectory, VfsDi
if(createMissingDirectories && !subdirectory->AssociatedDirectory())
{
NativePath currentPath;
OsPath currentPath;
if(directory->AssociatedDirectory()) // (is NULL when mounting into root)
currentPath = directory->AssociatedDirectory()->Path();
currentPath = Path::Join(currentPath, subdirectoryName);
currentPath = currentPath / subdirectoryName;
RETURN_ERR(CreateDirectory(currentPath));
@ -132,8 +132,8 @@ LibError vfs_Lookup(const VfsPath& pathname, VfsDirectory* startDirectory, VfsDi
if(pfile)
{
const NativePath& filename = pathname.substr(pos);
debug_assert(!filename.empty()); // asked for file but specified directory path
debug_assert(!pathname.IsDirectory());
const VfsPath filename = pathname.string().substr(pos);
*pfile = directory->GetFile(filename);
if(!*pfile)
return ERR::VFS_FILE_NOT_FOUND; // NOWARN

View File

@ -36,7 +36,8 @@
* there is no restriction on path length; when dimensioning character
* arrays, prefer PATH_MAX.
**/
typedef std::wstring VfsPath;
typedef Path VfsPath;
typedef std::vector<VfsPath> VfsPaths;

View File

@ -104,13 +104,12 @@ private:
LibError AddFiles(const FileInfos& files) const
{
const NativePath path(m_realDirectory->Path());
const OsPath path(m_realDirectory->Path());
for(size_t i = 0; i < files.size(); i++)
{
const NativePath pathname = Path::Join(path, files[i].Name());
const NativePath extension = Path::Extension(pathname);
if(wcscasecmp(extension.c_str(), L".zip") == 0)
const OsPath pathname = path / files[i].Name();
if(pathname.Extension() == L".zip")
{
PIArchiveReader archiveReader = CreateArchiveReader_Zip(pathname);
RETURN_ERR(archiveReader->ReadEntries(AddArchiveFile, (uintptr_t)this));
@ -128,7 +127,7 @@ private:
{
// skip version control directories - this avoids cluttering the
// VFS with hundreds of irrelevant files.
if(wcscasecmp(subdirectoryNames[i].c_str(), L".svn") == 0)
if(subdirectoryNames[i] == L".svn")
continue;
VfsDirectory* subdirectory = m_directory->AddSubdirectory(subdirectoryNames[i]);

View File

@ -35,7 +35,7 @@
//-----------------------------------------------------------------------------
VfsFile::VfsFile(const NativePath& name, size_t size, time_t mtime, size_t priority, const PIFileLoader& loader)
VfsFile::VfsFile(const VfsPath& name, size_t size, time_t mtime, size_t priority, const PIFileLoader& loader)
: m_name(name), m_size(size), m_mtime(mtime), m_priority(priority), m_loader(loader)
{
}
@ -78,7 +78,7 @@ static bool ShouldReplaceWith(const VfsFile& previousFile, const VfsFile& newFil
VfsFile* VfsDirectory::AddFile(const VfsFile& file)
{
std::pair<NativePath, VfsFile> value = std::make_pair(file.Name(), file);
std::pair<VfsPath, VfsFile> value = std::make_pair(file.Name(), file);
std::pair<VfsFiles::iterator, bool> ret = m_files.insert(value);
if(!ret.second) // already existed
{
@ -98,26 +98,26 @@ VfsFile* VfsDirectory::AddFile(const VfsFile& file)
// rationale: passing in a pre-constructed VfsDirectory and copying that into
// our map would be slower and less convenient for the caller.
VfsDirectory* VfsDirectory::AddSubdirectory(const NativePath& name)
VfsDirectory* VfsDirectory::AddSubdirectory(const VfsPath& name)
{
std::pair<NativePath, VfsDirectory> value = std::make_pair(name, VfsDirectory());
std::pair<VfsPath, VfsDirectory> value = std::make_pair(name.string(), VfsDirectory());
std::pair<VfsSubdirectories::iterator, bool> ret = m_subdirectories.insert(value);
return &(*ret.first).second;
}
VfsFile* VfsDirectory::GetFile(const NativePath& name)
VfsFile* VfsDirectory::GetFile(const VfsPath& name)
{
VfsFiles::iterator it = m_files.find(name);
VfsFiles::iterator it = m_files.find(name.string());
if(it == m_files.end())
return 0;
return &it->second;
}
VfsDirectory* VfsDirectory::GetSubdirectory(const NativePath& name)
VfsDirectory* VfsDirectory::GetSubdirectory(const VfsPath& name)
{
VfsSubdirectories::iterator it = m_subdirectories.find(name);
VfsSubdirectories::iterator it = m_subdirectories.find(name.string());
if(it == m_subdirectories.end())
return 0;
return &it->second;
@ -138,9 +138,9 @@ bool VfsDirectory::ShouldPopulate()
}
void VfsDirectory::Invalidate(const NativePath& name)
void VfsDirectory::Invalidate(const VfsPath& name)
{
m_files.erase(name);
m_files.erase(name.string());
m_shouldPopulate = 1;
}
@ -163,7 +163,7 @@ std::wstring FileDescription(const VfsFile& file)
wcsftime(timestamp, ARRAY_SIZE(timestamp), L"%a %b %d %H:%M:%S %Y", localtime(&mtime));
wchar_t buf[200];
swprintf_s(buf, ARRAY_SIZE(buf), L"(%c; %6lu; %ls) %ls", file.Loader()->LocationCode(), (unsigned long)file.Size(), timestamp, file.Name().c_str());
swprintf_s(buf, ARRAY_SIZE(buf), L"(%c; %6lu; %ls) %ls", file.Loader()->LocationCode(), (unsigned long)file.Size(), timestamp, file.Name().string().c_str());
return buf;
}
@ -195,10 +195,10 @@ void DirectoryDescriptionR(std::wstring& descriptions, const VfsDirectory& direc
const VfsDirectory::VfsSubdirectories& subdirectories = directory.Subdirectories();
for(VfsDirectory::VfsSubdirectories::const_iterator it = subdirectories.begin(); it != subdirectories.end(); ++it)
{
const NativePath& name = it->first;
const VfsPath& name = it->first;
const VfsDirectory& subdirectory = it->second;
descriptions += indentation;
descriptions += std::wstring(L"[") + name + L"]\n";
descriptions += std::wstring(L"[") + name.string() + L"]\n";
descriptions += FileDescriptions(subdirectory, indentLevel+1);
DirectoryDescriptionR(descriptions, subdirectory, indentLevel+1);

View File

@ -32,13 +32,14 @@
#include "lib/file/file_system.h" // FileInfo
#include "lib/file/common/file_loader.h" // PIFileLoader
#include "lib/file/common/real_directory.h" // PRealDirectory
#include "lib/file/vfs/vfs_path.h"
class VfsFile
{
public:
VfsFile(const NativePath& name, size_t size, time_t mtime, size_t priority, const PIFileLoader& provider);
VfsFile(const VfsPath& name, size_t size, time_t mtime, size_t priority, const PIFileLoader& provider);
const NativePath& Name() const
const VfsPath& Name() const
{
return m_name;
}
@ -64,7 +65,7 @@ public:
}
private:
NativePath m_name;
VfsPath m_name;
size_t m_size;
time_t m_mtime;
@ -77,8 +78,8 @@ private:
class VfsDirectory
{
public:
typedef std::map<NativePath, VfsFile> VfsFiles;
typedef std::map<NativePath, VfsDirectory> VfsSubdirectories;
typedef std::map<VfsPath, VfsFile> VfsFiles;
typedef std::map<VfsPath, VfsDirectory> VfsSubdirectories;
VfsDirectory();
@ -90,19 +91,19 @@ public:
/**
* @return address of existing or newly inserted subdirectory.
**/
VfsDirectory* AddSubdirectory(const NativePath& name);
VfsDirectory* AddSubdirectory(const VfsPath& name);
/**
* @return file with the given name.
* (note: non-const to allow changes to the file)
**/
VfsFile* GetFile(const NativePath& name);
VfsFile* GetFile(const VfsPath& name);
/**
* @return subdirectory with the given name.
* (note: non-const to allow changes to the subdirectory)
**/
VfsDirectory* GetSubdirectory(const NativePath& name);
VfsDirectory* GetSubdirectory(const VfsPath& name);
// note: exposing only iterators wouldn't enable callers to reserve space.
@ -137,7 +138,7 @@ public:
* indicate that a file has changed; ensure its new version supersedes
* the old by removing it and marking the directory for re-population.
**/
void Invalidate(const NativePath& name);
void Invalidate(const VfsPath& name);
/**
* empty file and subdirectory lists (e.g. when rebuilding VFS).

View File

@ -23,43 +23,34 @@
#ifndef INCLUDED_NATIVE_PATH
#define INCLUDED_NATIVE_PATH
#include <string>
#include "lib/path_util.h"
// rationale:
// this is conceptually a different kind of path, not a superset of VfsPath,
// hence NativePath instead of Path (PathUtil is a bit clunky as a
// namespace anyway).
// a typedef instead of wrapper class avoids the need for accessor functions
// (e.g. boost::filesystem::string()) at the cost of somewhat diminished safety.
// users are responsible for ensuring the path doesn't contain any forbidden
// characters (including any code points >= 0x100 on anything but Windows)
typedef std::wstring NativePath;
static inline NativePath NativePathFromString(const std::string& string)
{
return NativePath(string.begin(), string.end());
}
typedef Path OsPath;
#if OS_WIN
static inline std::wstring StringFromNativePath(const NativePath& npath)
static inline const Path::String& OsString(const OsPath& path)
{
return npath;
return path.string();
}
#else
static inline std::string StringFromNativePath(const NativePath& npath)
static inline std::string OsString(const OsPath& path)
{
std::string string(npath.length(), '\0');
for(size_t i = 0; i < npath.length(); i++)
const Path::String& wstring = path.string();
std::string string(wstring.length(), '\0');
for(size_t i = 0; i < wstring.length(); i++)
{
debug_assert(npath[i] <= UCHAR_MAX);
string[i] = npath[i];
debug_assert(wstring[i] <= UCHAR_MAX);
string[i] = wstring[i];
}
return string;
}
#endif
#endif // #ifndef INCLUDED_NATIVE_PATH

View File

@ -77,32 +77,6 @@ bool path_is_subpath(const wchar_t* s1, const wchar_t* s2)
}
// if name is invalid, return a descriptive error code, otherwise INFO::OK.
// (name is a path component, i.e. that between directory separators)
LibError path_component_validate(const wchar_t* name)
{
// disallow empty strings
if(*name == '\0')
WARN_RETURN(ERR::PATH_EMPTY);
for(;;)
{
const int c = *name++;
// disallow *any* dir separators (regardless of which
// platform we're on).
if(c == '\\' || c == ':' || c == '/')
WARN_RETURN(ERR::PATH_COMPONENT_SEPARATOR);
// end of string, no errors encountered
if(c == '\0')
break;
}
return INFO::OK;
}
//-----------------------------------------------------------------------------
// return pointer to the name component within path (i.e. skips over all
@ -117,7 +91,5 @@ const wchar_t* path_name_only(const wchar_t* path)
// return name, i.e. component after the last slash
const wchar_t* name = std::max(slash1, slash2)+1;
if(name[0] != '\0') // else path_component_validate would complain
path_component_validate(name);
return name;
}

View File

@ -37,8 +37,9 @@
#ifndef INCLUDED_PATH_UTIL
#define INCLUDED_PATH_UTIL
#include "lib/native_path.h"
#include "lib/posix/posix_filesystem.h"
#if CONFIG_ENABLE_BOOST
# include "boost/functional/hash.hpp"
#endif
namespace ERR
{
@ -47,13 +48,6 @@ namespace ERR
const LibError PATH_NOT_FOUND = -100302;
}
/**
* check if name is valid. (see source for criteria)
*
* @return LibError (ERR::PATH_* or INFO::OK)
**/
LIB_API LibError path_component_validate(const wchar_t* name);
/**
* is s2 a subpath of s1, or vice versa? (equal counts as subpath)
*
@ -63,141 +57,168 @@ LIB_API LibError path_component_validate(const wchar_t* name);
LIB_API bool path_is_subpath(const wchar_t* s1, const wchar_t* s2);
/**
* Get the name component of a path.
* Get the path component of a path.
* Skips over all characters up to the last dir separator, if any.
*
* @param path Input path.
* @return pointer to name component within \<path\>.
* @return pointer to path component within \<path\>.
**/
LIB_API const wchar_t* path_name_only(const wchar_t* path);
namespace Path {
template<class Path_t>
static inline bool IsDirectory(const Path_t& pathname)
// NB: there is a need for 'generic' paths (e.g. for Trace entry / archive pathnames).
// converting via c_str would be inefficient, and the Os/VfsPath typedefs are hopefully
// sufficient to avoid errors.
class Path
{
if(pathname.empty()) // (ensure length()-1 is safe)
return true; // (the VFS root directory is represented as an empty string)
public:
typedef std::wstring 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[pathname.length()-1] == '/' || pathname[pathname.length()-1] == '\\';
}
Path() {}
Path(const char* p) : path(p, p+strlen(p)) {}
Path(const wchar_t* p) : path(p, p+wcslen(p)) {}
Path(const std::string& s) : path(s.begin(), s.end()) {}
Path(const std::wstring& s) : path(s) {}
template<class Path_t>
static inline Path_t Path(const Path_t& pathname)
{
size_t n = pathname.find_last_of('/');
if(n == Path_t::npos)
bool empty() const
{
n = pathname.find_last_of('\\');
if(n == Path_t::npos)
return L"";
return path.empty();
}
return pathname.substr(0, n);
}
template<class Path_t>
static inline Path_t Filename(const Path_t& pathname)
{
size_t n = pathname.find_last_of('/');
if(n == Path_t::npos)
const String& string() const
{
n = pathname.find_last_of('\\');
if(n == Path_t::npos)
return pathname;
return path;
}
return pathname.substr(n+1);
}
template<class Path_t>
static inline Path_t Basename(const Path_t& pathname)
{
const Path_t filename = Filename(pathname);
const size_t idxDot = filename.find_last_of('.');
if(idxDot == Path_t::npos)
return filename;
return filename.substr(0, idxDot);
}
template<class Path_t>
static inline std::wstring Extension(const Path_t& pathname)
{
const size_t idxDot = pathname.find_last_of('.');
if(idxDot == Path_t::npos)
return Path_t();
return pathname.substr(idxDot);
}
static inline std::wstring JoinPathStrings(const std::wstring& path1, const std::wstring& path2)
{
std::wstring ret = path1;
if(!IsDirectory(path1))
ret += '/';
ret += path2;
return ret;
}
template<class Path_t>
static inline Path_t Join(const Path_t& path1, const Path_t& path2)
{
return JoinPathStrings(path1, path2);
}
template<class Path_t>
static inline Path_t Join(const Path_t& path1, const char* literal)
{
return JoinPathStrings(path1, NativePathFromString(literal));
}
template<class Path_t>
static inline Path_t Join(const char* literal, const Path_t& path2)
{
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
static inline bool FileExists(const NativePath& pathname)
{
struct stat s;
const bool exists = wstat(pathname.c_str(), &s) == 0;
return exists;
}
static inline u64 FileSize(const NativePath& pathname)
{
struct stat s;
debug_assert(wstat(pathname.c_str(), &s) == 0);
return s.st_size;
}
static inline bool DirectoryExists(const NativePath& path)
{
WDIR* dir = wopendir(path.c_str());
if(dir)
bool operator<(const Path& rhs) const
{
wclosedir(dir);
return true;
return wcscasecmp(path.c_str(), rhs.path.c_str()) < 0;
}
return false;
bool operator==(const Path& rhs) const
{
return wcscasecmp(path.c_str(), rhs.path.c_str()) == 0;
}
bool operator!=(const Path& rhs) const
{
return !operator==(rhs);
}
bool IsDirectory() const
{
if(empty()) // (ensure length()-1 is safe)
return true; // (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 separators.
// we therefore allow all separators here.
return path[path.length()-1] == '/' || path[path.length()-1] == '\\';
}
Path Parent() const
{
size_t idxSlash = path.find_last_of('/');
if(idxSlash == String::npos)
{
idxSlash = path.find_last_of('\\');
if(idxSlash == String::npos)
return L"";
}
return path.substr(0, idxSlash);
}
Path Filename() const
{
size_t idxSlash = path.find_last_of('/');
if(idxSlash == String::npos)
{
idxSlash = path.find_last_of('\\');
if(idxSlash == String::npos)
return path;
}
return path.substr(idxSlash+1);
}
Path Basename() const
{
const Path filename = Filename();
const size_t idxDot = filename.string().find_last_of('.');
if(idxDot == String::npos)
return filename;
return filename.string().substr(0, idxDot);
}
// (Path return type allows callers to use our operator==)
Path Extension() const
{
const Path filename = Filename();
const size_t idxDot = filename.string().find_last_of('.');
if(idxDot == String::npos)
return Path();
return filename.string().substr(idxDot);
}
Path ChangeExtension(Path extension) const
{
return Parent() / Path(Basename().string() + extension.string());
}
Path operator/(Path rhs) const
{
Path ret = *this;
if(!ret.IsDirectory())
ret.path += '/';
ret.path += rhs.path;
return ret;
}
LibError Validate() const
{
for(size_t i = 0; i < path.length(); i++)
{
}
return INFO::OK;
}
private:
String path;
};
static inline std::wostream& operator<<(std::wostream& s, const Path& path)
{
s << path.string();
return s;
}
static inline std::wistream& operator>>(std::wistream& s, Path& path)
{
Path::String string;
s >> string;
path = Path(string);
return s;
}
#if CONFIG_ENABLE_BOOST
namespace boost {
template<>
struct hash<Path> : std::unary_function<Path, std::size_t>
{
std::size_t operator()(const Path& path) const
{
return hash_value(path.string());
}
};
}
#endif // #if CONFIG_ENABLE_BOOST
#endif // #ifndef INCLUDED_PATH_UTIL

View File

@ -188,21 +188,20 @@ static void Cursor_dtor(Cursor* c)
static LibError Cursor_reload(Cursor* c, const PIVFS& vfs, const VfsPath& name, Handle)
{
const VfsPath path(L"art/textures/cursors");
const VfsPath pathname(Path::Join(path, name));
const VfsPath pathname(VfsPath(L"art/textures/cursors") / name);
// read pixel offset of the cursor's hotspot [the bit of it that's
// drawn at (g_mouse_x,g_mouse_y)] from file.
int hotspotx = 0, hotspoty = 0;
{
const VfsPath pathnameHotspot = Path::ChangeExtension(pathname, L".txt");
const VfsPath pathnameHotspot = pathname.ChangeExtension(L".txt");
shared_ptr<u8> buf; size_t size;
RETURN_ERR(vfs->LoadFile(pathnameHotspot, buf, size));
std::wstringstream s(std::wstring((const wchar_t*)buf.get(), size));
s >> hotspotx >> hotspoty;
}
const VfsPath pathnameImage = Path::ChangeExtension(pathname, L".png");
const VfsPath pathnameImage = pathname.ChangeExtension(L".png");
// try loading as system cursor (2d, hardware accelerated)
if(load_sys_cursor(vfs, pathnameImage, hotspotx, hotspoty, &c->system_cursor) == INFO::OK)

View File

@ -165,7 +165,7 @@ static LibError Ogl_Shader_reload(Ogl_Shader* shdr, const PIVFS& vfs, const VfsP
{
char* infolog = new char[log_length];
pglGetShaderInfoLog(shdr->id, log_length, 0, infolog);
debug_printf(L"Compile log for shader %ls (type %ls):\n%hs", pathname.c_str(), type.c_str(), infolog);
debug_printf(L"Compile log for shader %ls (type %ls):\n%hs", pathname.string().c_str(), type.c_str(), infolog);
delete[] infolog;
}
@ -177,7 +177,7 @@ static LibError Ogl_Shader_reload(Ogl_Shader* shdr, const PIVFS& vfs, const VfsP
// useful some time.
ogl_WarnIfError();
debug_printf(L"Failed to compile shader %ls (type %ls)\n", pathname.c_str(), type.c_str());
debug_printf(L"Failed to compile shader %ls (type %ls)\n", pathname.string().c_str(), type.c_str());
err = ERR::SHDR_COMPILE;
goto fail_shadercreated;
@ -284,7 +284,7 @@ static LibError do_load_shader(
if (Type.empty())
{
LOGERROR(L"%ls: Missing attribute \"type\" in element \"Shader\".", pathname.c_str());
LOGERROR(L"%ls: Missing attribute \"type\" in element \"Shader\".", pathname.string().c_str());
WARN_RETURN(ERR::CORRUPTED);
}
@ -292,7 +292,7 @@ static LibError do_load_shader(
if (!shadertype)
{
LOGERROR(L"%ls: Unknown shader type \"%hs\" (valid are: VERTEX_SHADER, FRAGMENT_SHADER).", pathname.c_str(), Type.c_str());
LOGERROR(L"%ls: Unknown shader type \"%hs\" (valid are: VERTEX_SHADER, FRAGMENT_SHADER).", pathname.string().c_str(), Type.c_str());
WARN_RETURN(ERR::CORRUPTED);
}
@ -300,7 +300,7 @@ static LibError do_load_shader(
if (pathnameShader.empty())
{
LOGERROR(L"%ls: Missing shader name.", pathname.c_str());
LOGERROR(L"%ls: Missing shader name.", pathname.string().c_str());
WARN_RETURN(ERR::CORRUPTED);
}
@ -355,7 +355,7 @@ static LibError Ogl_Program_reload(Ogl_Program* p, const PIVFS& vfs, const VfsPa
if (Root.GetNodeName() != el_program)
{
LOGERROR(L"%ls: XML root was not \"Program\".", pathname.c_str());
LOGERROR(L"%ls: XML root was not \"Program\".", pathname.string().c_str());
WARN_RETURN(ERR::CORRUPTED);
}
@ -376,7 +376,7 @@ static LibError Ogl_Program_reload(Ogl_Program* p, const PIVFS& vfs, const VfsPa
if (Shader.GetNodeName() != el_shader)
{
LOGERROR(L"%ls: Only \"Shader\" may be child of \"Shaders\".", pathname.c_str());
LOGERROR(L"%ls: Only \"Shader\" may be child of \"Shaders\".", pathname.string().c_str());
WARN_RETURN(ERR::CORRUPTED);
}
@ -385,7 +385,7 @@ static LibError Ogl_Program_reload(Ogl_Program* p, const PIVFS& vfs, const VfsPa
}
else
{
LOGWARNING(L"%ls: Unknown child of \"Program\".", pathname.c_str());
LOGWARNING(L"%ls: Unknown child of \"Program\".", pathname.string().c_str());
}
}
@ -403,13 +403,13 @@ static LibError Ogl_Program_reload(Ogl_Program* p, const PIVFS& vfs, const VfsPa
{
char* infolog = new char[log_length];
pglGetProgramInfoLog(p->id, log_length, 0, infolog);
debug_printf(L"Linker log for %ls:\n%hs\n", pathname.c_str(), infolog);
debug_printf(L"Linker log for %ls:\n%hs\n", pathname.string().c_str(), infolog);
delete[] infolog;
}
if (!linked)
{
debug_printf(L"Link failed for %ls\n", pathname.c_str());
debug_printf(L"Link failed for %ls\n", pathname.string().c_str());
WARN_RETURN(ERR::SHDR_LINK);
}

View File

@ -517,7 +517,7 @@ Handle ogl_tex_load(const PIVFS& vfs, const VfsPath& pathname, size_t flags)
// is still in memory; otherwise, a negative error code.
Handle ogl_tex_find(const VfsPath& pathname)
{
const uintptr_t key = fnv_hash(pathname.c_str(), pathname.length()*sizeof(pathname[0]));
const uintptr_t key = fnv_hash(pathname.string().c_str(), pathname.string().length()*sizeof(pathname.string()[0]));
return h_find(H_OglTex, key);
}

View File

@ -28,7 +28,7 @@
class TestTex : public CxxTest::TestSuite
{
void generate_encode_decode_compare(size_t w, size_t h, size_t flags, size_t bpp, const NativePath& extension)
void generate_encode_decode_compare(size_t w, size_t h, size_t flags, size_t bpp, const OsPath& extension)
{
// generate test data
const size_t size = w*h*bpp/8;

View File

@ -85,8 +85,8 @@ static LibError UniFont_reload(UniFont* f, const PIVFS& vfs, const VfsPath& base
// Read font definition file into a stringstream
shared_ptr<u8> buf; size_t size;
const VfsPath fntName(basename + L".fnt");
RETURN_ERR(vfs->LoadFile(Path::Join(path, fntName), buf, size)); // [cumulative for 12: 36ms]
const VfsPath fntName(basename.ChangeExtension(L".fnt"));
RETURN_ERR(vfs->LoadFile(path / fntName, buf, size)); // [cumulative for 12: 36ms]
std::istringstream FNTStream(std::string((const char*)buf.get(), size));
int Version;
@ -150,8 +150,8 @@ static LibError UniFont_reload(UniFont* f, const PIVFS& vfs, const VfsPath& base
// Load glyph texture
// [cumulative for 12: 20ms]
const VfsPath imgName(basename + L".png");
Handle ht = ogl_tex_load(vfs, Path::Join(path, imgName));
const VfsPath imgName(basename.ChangeExtension(L".png"));
Handle ht = ogl_tex_load(vfs, path / imgName);
RETURN_ERR(ht);
(void)ogl_tex_set_filter(ht, GL_NEAREST);
// override is necessary because the GL format is chosen as LUMINANCE,
@ -188,7 +188,7 @@ static LibError UniFont_to_string(const UniFont* f, wchar_t* buf)
if (f->ht) // not true if this is called after dtor (which it is)
{
const VfsPath& path = h_filename(f->ht);
swprintf_s(buf, H_STRING_LEN, L"Font %ls", path.c_str());
swprintf_s(buf, H_STRING_LEN, L"Font %ls", path.string().c_str());
}
else
swprintf_s(buf, H_STRING_LEN, L"Font");

View File

@ -572,7 +572,7 @@ Handle h_alloc(H_Type type, const PIVFS& vfs, const VfsPath& pathname, size_t fl
{
RETURN_ERR(type_validate(type));
const uintptr_t key = fnv_hash(pathname.c_str(), pathname.length()*sizeof(pathname[0]));
const uintptr_t key = fnv_hash(pathname.string().c_str(), pathname.string().length()*sizeof(pathname.string()[0]));
// see if we can reuse an existing handle
Handle h = reuse_existing_handle(key, type, flags);
@ -622,7 +622,7 @@ static LibError h_free_idx(ssize_t idx, HDATA* hd)
wchar_t buf[H_STRING_LEN];
if(vtbl->to_string(hd->user, buf) < 0)
wcscpy_s(buf, ARRAY_SIZE(buf), L"(error)");
debug_printf(L"H_MGR| free %ls %ls accesses=%lu %ls\n", hd->type->name, hd->pathname.c_str(), (unsigned long)hd->num_derefs, buf);
debug_printf(L"H_MGR| free %ls %ls accesses=%lu %ls\n", hd->type->name, hd->pathname.string().c_str(), (unsigned long)hd->num_derefs, buf);
}
#endif
@ -690,7 +690,7 @@ VfsPath h_filename(const Handle h)
if(!hd)
{
debug_assert(0);
return 0;
return VfsPath();
}
return hd->pathname;
}
@ -699,7 +699,7 @@ VfsPath h_filename(const Handle h)
// TODO: what if iterating through all handles is too slow?
LibError h_reload(const PIVFS& vfs, const VfsPath& pathname)
{
const u32 key = fnv_hash(pathname.c_str(), pathname.length()*sizeof(pathname[0]));
const u32 key = fnv_hash(pathname.string().c_str(), pathname.string().length()*sizeof(pathname.string()[0]));
// destroy (note: not free!) all handles backed by this file.
// do this before reloading any of them, because we don't specify reload

View File

@ -5,8 +5,8 @@
#include "lib/external_libraries/vorbis.h"
#include "lib/byte_order.h"
#include "lib/path_util.h"
#include "lib/file/file.h"
#include "lib/file/file_system_util.h"
static LibError LibErrorFromVorbis(int err)
@ -52,7 +52,7 @@ class VorbisFileAdapter
public:
VorbisFileAdapter(const PFile& openedFile)
: file(openedFile)
, size(FileSize(openedFile->Pathname()))
, size(fs_util::FileSize(openedFile->Pathname()))
, offset(0)
{
}
@ -258,7 +258,7 @@ private:
//-----------------------------------------------------------------------------
LibError OpenOggStream(const NativePath& pathname, OggStreamPtr& stream)
LibError OpenOggStream(const OsPath& pathname, OggStreamPtr& stream)
{
PFile file(new File);
RETURN_ERR(file->Open(pathname, L'r'));

View File

@ -19,7 +19,7 @@ public:
typedef shared_ptr<OggStream> OggStreamPtr;
extern LibError OpenOggStream(const NativePath& pathname, OggStreamPtr& stream);
extern LibError OpenOggStream(const OsPath& pathname, OggStreamPtr& stream);
/**
* A non-streaming OggStream (reading the whole file in advance)

View File

@ -1296,7 +1296,7 @@ static LibError VSrc_reload(VSrc* vs, const PIVFS& vfs, const VfsPath& pathname,
// pathname is a definition file containing the data file name and
// its gain.
if(fs::extension(pathname) == L".txt")
if(pathname.Extension() == L".txt")
{
shared_ptr<u8> buf; size_t size;
RETURN_ERR(vfs->LoadFile(pathname, buf, size));

View File

@ -257,33 +257,6 @@ int tsprintf_s(tchar* buf, size_t max_chars, const tchar* fmt, ...)
return len;
}
// note: there is no portable wfopen, so we need separate implementations
// of tfopen_s. (the Unicode version just converts to UTF8)
#if defined(WSECURE_CRT)
errno_t _wfopen_s(FILE** pfile, const wchar_t* filename, const wchar_t* mode)
{
*pfile = NULL;
const std::string filename_c = utf8_from_wstring(filename);
const std::string mode_c = utf8_from_wstring(mode);
return fopen_s(pfile, filename_c.c_str(), mode_c.c_str());
}
#else
errno_t fopen_s(FILE** pfile, const char* filename, const char* mode)
{
*pfile = NULL;
FILE* file = fopen(filename, mode);
if(!file)
return ENOENT;
*pfile = file;
return 0;
}
#endif
#endif // #if EMULATE_SECURE_CRT
#undef tchar

View File

@ -98,10 +98,6 @@ extern int vswprintf_s(wchar_t* dst, size_t max_dst_chars, const wchar_t* fmt, v
extern int sprintf_s(char* buf, size_t max_chars, const char* fmt, ...) PRINTF_ARGS(3);
extern int swprintf_s(wchar_t* buf, size_t max_chars, const wchar_t* fmt, ...) WPRINTF_ARGS(3);
typedef int errno_t;
extern errno_t fopen_s(FILE** pfile, const char* filename, const char* mode);
extern errno_t _wfopen_s(FILE** pfile, const wchar_t* filename, const wchar_t* mode);
// we'd like to avoid deprecation warnings caused by scanf. selective
// 'undeprecation' isn't possible, replacing all stdio declarations with
// our own deprecation scheme is a lot of work, suppressing all deprecation

View File

@ -266,6 +266,8 @@ namespace CxxTest
#define TSM_ASSERT_STR_EQUALS(m, str1, str2) TSM_ASSERT_EQUALS(m, std::string(str1), std::string(str2))
#define TS_ASSERT_WSTR_EQUALS(str1, str2) TS_ASSERT_EQUALS(std::wstring(str1), std::wstring(str2))
#define TSM_ASSERT_WSTR_EQUALS(m, str1, str2) TSM_ASSERT_EQUALS(m, std::wstring(str1), std::wstring(str2))
#define TS_ASSERT_PATH_EQUALS(path1, path2) TS_ASSERT_EQUALS(path1.string(), path2.string())
#define TSM_ASSERT_PATH_EQUALS(m, path1, path2) TSM_ASSERT_EQUALS(m, path1.string(), path2.string())
bool ts_str_contains(const std::wstring& str1, const std::wstring& str2); // defined in test_setup.cpp
#define TS_ASSERT_WSTR_CONTAINS(str1, str2) TSM_ASSERT(str1, ts_str_contains(str1, str2))
@ -285,6 +287,6 @@ void ScriptTestSetup(ScriptInterface&);
// Default game data directory
// (TODO: game-specific functions like this probably shouldn't be inside lib/, but it's useful
// here since lots of tests use it)
NativePath DataDir(); // defined in test_setup.cpp
OsPath DataDir(); // defined in test_setup.cpp
#endif // #ifndef INCLUDED_SELF_TEST

View File

@ -27,7 +27,7 @@
#ifndef INCLUDED_DIR_WATCH
#define INCLUDED_DIR_WATCH
#include "lib/path_util.h"
#include "lib/native_path.h"
struct DirWatch;
typedef shared_ptr<DirWatch> PDirWatch;
@ -49,7 +49,7 @@ typedef shared_ptr<DirWatch> PDirWatch;
* convenient to store PDirWatch there instead of creating a second
* tree structure here.
**/
LIB_API LibError dir_watch_Add(const NativePath& path, PDirWatch& dirWatch);
LIB_API LibError dir_watch_Add(const OsPath& path, PDirWatch& dirWatch);
class DirWatchNotification
{
@ -61,12 +61,12 @@ public:
Changed
};
DirWatchNotification(const NativePath& pathname, EType type)
DirWatchNotification(const OsPath& pathname, EType type)
: pathname(pathname), type(type)
{
}
const NativePath& Pathname() const
const OsPath& Pathname() const
{
return pathname;
}
@ -77,7 +77,7 @@ public:
}
private:
NativePath pathname;
OsPath pathname;
EType type;
};

View File

@ -27,6 +27,9 @@
#ifndef INCLUDED_FILESYSTEM
#define INCLUDED_FILESYSTEM
#include "lib/native_path.h"
#include "lib/posix/posix_filesystem.h" // mode_t
//
// dirent.h
@ -42,7 +45,7 @@ struct wdirent
wchar_t* d_name;
};
extern WDIR* wopendir(const wchar_t* path);
extern WDIR* wopendir(const OsPath& path);
extern struct wdirent* wreaddir(WDIR*);
@ -74,8 +77,8 @@ extern int wclosedir(WDIR*);
#define O_NONBLOCK 0x1000000
#endif
extern int wopen(const wchar_t* pathname, int oflag);
extern int wopen(const wchar_t* pathname, int oflag, mode_t mode);
extern int wopen(const OsPath& pathname, int oflag);
extern int wopen(const OsPath& pathname, int oflag, mode_t mode);
extern int wclose(int fd);
@ -83,33 +86,33 @@ extern int wclose(int fd);
// unistd.h
//
LIB_API int wtruncate(const wchar_t* pathname, off_t length);
LIB_API int wtruncate(const OsPath& pathname, off_t length);
LIB_API int wunlink(const wchar_t* pathname);
LIB_API int wunlink(const OsPath& pathname);
LIB_API int wrmdir(const wchar_t* path);
LIB_API int wrmdir(const OsPath& path);
//
// stdio.h
//
LIB_API int wrename(const wchar_t* pathnameOld, const wchar_t* pathnameNew);
LIB_API int wrename(const OsPath& pathnameOld, const OsPath& pathnameNew);
//
// stdlib.h
//
LIB_API wchar_t* wrealpath(const wchar_t* pathname, wchar_t* resolved);
LIB_API OsPath wrealpath(const OsPath& pathname);
//
// sys/stat.h
//
LIB_API int wstat(const wchar_t* pathname, struct stat* buf);
LIB_API int wstat(const OsPath& pathname, struct stat* buf);
LIB_API int wmkdir(const wchar_t* path, mode_t mode);
LIB_API int wmkdir(const OsPath& path, mode_t mode);
#endif // #ifndef INCLUDED_FILESYSTEM

View File

@ -74,7 +74,7 @@ struct DirWatch
FAMCancelMonitor(&fc, &req);
}
NativePath path;
OsPath path;
int reqnum;
};
@ -155,7 +155,7 @@ static void* fam_event_loop(void*)
}
}
LibError dir_watch_Add(const NativePath& npath, PDirWatch& dirWatch)
LibError dir_watch_Add(const OsPath& path, PDirWatch& dirWatch)
{
// init already failed; don't try again or complain
if(initialized == -1)
@ -188,16 +188,15 @@ LibError dir_watch_Add(const NativePath& npath, PDirWatch& dirWatch)
// but it would only save tens of milliseconds of CPU time, so it's probably
// not worthwhile
const std::string path = StringFromNativePath(npath);
FAMRequest req;
if(FAMMonitorDirectory(&fc, path.c_str(), &req, tmpDirWatch.get()) < 0)
if(FAMMonitorDirectory(&fc, OsString(path).c_str(), &req, tmpDirWatch.get()) < 0)
{
debug_warn(L"res_watch_dir failed!");
WARN_RETURN(ERR::FAIL); // no way of getting error code?
}
dirWatch.swap(tmpDirWatch);
dirWatch->path = npath;
dirWatch->path = path;
dirWatch->reqnum = req.reqnum;
return INFO::OK;
@ -209,7 +208,7 @@ LibError dir_watch_Poll(DirWatchNotifications& notifications)
{
if(initialized == -1)
return ERR::FAIL; // NOWARN
if(!initialized) // XXX Fix Atlas instead of supressing the warning
if(!initialized) // XXX Fix Atlas instead of suppressing the warning
return ERR::FAIL; //WARN_RETURN(ERR::LOGIC);
std::vector<NotificationEvent> polled_notifications;
@ -236,7 +235,7 @@ LibError dir_watch_Poll(DirWatchNotifications& notifications)
continue;
}
DirWatch* dirWatch = (DirWatch*)polled_notifications[i].userdata;
NativePath pathname = Path::Join(dirWatch->path, NativePathFromString(polled_notifications[i].filename));
OsPath pathname = dirWatch->path / polled_notifications[i].filename;
notifications.push_back(DirWatchNotification(pathname, type));
}

View File

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

View File

@ -25,7 +25,7 @@
// stub implementations
LibError dir_watch_Add(const NativePath& UNUSED(path), PDirWatch& UNUSED(dirWatch))
LibError dir_watch_Add(const OsPath& UNUSED(path), PDirWatch& UNUSED(dirWatch))
{
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(NativePath& pathname)
LibError sys_get_executable_name(OsPath& pathname)
{
static char name[PATH_MAX];
static bool init = false;
@ -102,7 +102,7 @@ LibError sys_get_executable_name(NativePath& pathname)
debug_printf(L"app bundle name: %hs\n", name);
}
pathname = NativePathFromString(name);
pathname = name;
return INFO::OK;
}

View File

@ -34,14 +34,13 @@
struct WDIR
{
DIR* d;
wchar_t name[300];
wchar_t name[PATH_MAX];
wdirent ent;
};
WDIR* wopendir(const wchar_t* wpath)
WDIR* wopendir(const OsPath& path)
{
const std::string path = StringFromNativePath(wpath);
DIR* d = opendir(path.c_str());
DIR* d = opendir(OsString(path).c_str());
if(!d)
return 0;
WDIR* wd = new WDIR;
@ -56,8 +55,7 @@ struct wdirent* wreaddir(WDIR* wd)
dirent* ent = readdir(wd->d);
if(!ent)
return 0;
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), ent->d_name);
return &wd->ent;
}
@ -69,17 +67,15 @@ int wclosedir(WDIR* wd)
}
int wopen(const wchar_t* wpathname, int oflag)
int wopen(const OsPath& pathname, int oflag)
{
debug_assert(!(oflag & O_CREAT));
const std::string pathname = StringFromNativePath(wpathname);
return open(pathname.c_str(), oflag);
return open(OsString(pathname).c_str(), oflag);
}
int wopen(const wchar_t* wpathname, int oflag, mode_t mode)
int wopen(const OsPath& pathname, int oflag, mode_t mode)
{
const std::string pathname = StringFromNativePath(wpathname);
return open(pathname.c_str(), oflag, mode);
return open(OsString(pathname).c_str(), oflag, mode);
}
int wclose(int fd)
@ -88,51 +84,41 @@ int wclose(int fd)
}
int wtruncate(const wchar_t* wpathname, off_t length)
int wtruncate(const OsPath& pathname, off_t length)
{
const std::string pathname = StringFromNativePath(wpathname);
return truncate(pathname.c_str(), length);
return truncate(OsString(pathname).c_str(), length);
}
int wunlink(const wchar_t* wpathname)
int wunlink(const OsPath& pathname)
{
const std::string pathname = StringFromNativePath(wpathname);
return unlink(pathname.c_str());
return unlink(OsString(pathname).c_str());
}
int wrmdir(const wchar_t* wpath)
int wrmdir(const OsPath& path)
{
const std::string path = StringFromNativePath(wpath);
return rmdir(path.c_str());
return rmdir(OsString(path).c_str());
}
int wrename(const wchar_t* wpathnameOld, const wchar_t* wpathnameNew)
int wrename(const OsPath& pathnameOld, const OsPath& pathnameNew)
{
const std::string pathnameOld = StringFromNativePath(wpathnameOld);
const std::string pathnameNew = StringFromNativePath(wpathnameNew);
return rename(pathnameOld.c_str(), pathnameNew.c_str());
return rename(OsString(pathnameOld).c_str(), OsString(pathnameNew).c_str());
}
wchar_t* wrealpath(const wchar_t* wpathname, wchar_t* wresolved)
OsPath realpath(const OsPath& pathname)
{
char resolvedBuf[PATH_MAX];
const std::string pathname = StringFromNativePath(wpathname);
const char* resolved = realpath(pathname.c_str(), resolvedBuf);
const char* resolved = realpath(OsString(pathname).c_str(), resolvedBuf);
if(!resolved)
return 0;
NativePath nresolved = NativePathFromString(resolved);
wcscpy_s(wresolved, PATH_MAX, nresolved.c_str());
return wresolved;
return OsPath();
return resolved;
}
int wstat(const wchar_t* wpathname, struct stat* buf)
int wstat(const OsPath& pathname, struct stat* buf)
{
const std::string pathname = StringFromNativePath(wpathname);
return stat(pathname.c_str(), buf);
return stat(OsString(pathname).c_str(), buf);
}
int wmkdir(const wchar_t* wpath, mode_t mode)
int wmkdir(const OsPath& path, mode_t mode)
{
const std::string path = StringFromNativePath(wpath);
return mkdir(path.c_str(), mode);
return mkdir(OsString(path).c_str(), mode);
}

View File

@ -260,7 +260,7 @@ static void UninstallDriver()
}
static void StartDriver(const NativePath& driverPathname)
static void StartDriver(const OsPath& driverPathname)
{
const SC_HANDLE hSCM = OpenServiceControlManager();
if(!hSCM)
@ -290,7 +290,7 @@ static void StartDriver(const NativePath& driverPathname)
// NB: Windows 7 seems to insist upon backslashes (i.e. external_file_string)
hService = CreateServiceW(hSCM, AKEN_NAME, AKEN_NAME,
SERVICE_ALL_ACCESS, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
driverPathname.c_str(), 0, 0, 0, startName, 0);
OsString(driverPathname).c_str(), 0, 0, 0, startName, 0);
debug_assert(hService != 0);
}
@ -323,7 +323,7 @@ static bool Is64BitOs()
#endif
}
static NativePath DriverPathname()
static OsPath DriverPathname()
{
const char* const bits = Is64BitOs()? "64" : "";
#ifdef NDEBUG
@ -333,7 +333,7 @@ static NativePath DriverPathname()
#endif
char filename[PATH_MAX];
sprintf_s(filename, ARRAY_SIZE(filename), "aken%s%s.sys", bits, debug);
return Path::Join(wutil_ExecutablePath(), filename);
return wutil_ExecutablePath() / filename;
}
@ -345,7 +345,7 @@ static LibError Init()
return ERR::NOT_SUPPORTED; // NOWARN
{
const NativePath driverPathname = DriverPathname();
const OsPath driverPathname = DriverPathname();
StartDriver(driverPathname);
}

View File

@ -1871,8 +1871,8 @@ void wdbg_sym_WriteMinidump(EXCEPTION_POINTERS* exception_pointers)
WinScopedLock lock(WDBG_SYM_CS);
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);
OsPath path = ah_get_log_dir()/"crashlog.dmp";
HANDLE hFile = CreateFileW(OsString(path).c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, 0, CREATE_ALWAYS, 0, 0);
if(hFile == INVALID_HANDLE_VALUE)
{
DEBUG_DISPLAY_ERROR(L"wdbg_sym_WriteMinidump: unable to create crashlog.dmp.");

View File

@ -44,12 +44,12 @@ WINIT_REGISTER_MAIN_SHUTDOWN(wdir_watch_Shutdown);
class DirHandle
{
public:
DirHandle(const NativePath& path)
DirHandle(const OsPath& path)
{
WinScopedPreserveLastError s; // CreateFile
const DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
const DWORD flags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED;
m_hDir = CreateFileW(path.c_str(), FILE_LIST_DIRECTORY, share, 0, OPEN_EXISTING, flags, 0);
m_hDir = CreateFileW(OsString(path).c_str(), FILE_LIST_DIRECTORY, share, 0, OPEN_EXISTING, flags, 0);
}
~DirHandle()
@ -81,7 +81,7 @@ class DirWatchRequest
{
NONCOPYABLE(DirWatchRequest);
public:
DirWatchRequest(const NativePath& path)
DirWatchRequest(const OsPath& path)
: m_path(path), m_dirHandle(path), m_data(new u8[dataSize])
{
m_ovl = (OVERLAPPED*)calloc(1, sizeof(OVERLAPPED)); // rationale for dynamic alloc: see decl
@ -124,7 +124,7 @@ public:
}
}
const NativePath& Path() const
const OsPath& Path() const
{
return m_path;
}
@ -162,12 +162,12 @@ public:
const FILE_NOTIFY_INFORMATION* fni = (const FILE_NOTIFY_INFORMATION*)m_data;
for(;;)
{
// convert name from BSTR (non-zero-terminated) to NativePath
// convert name from BSTR (non-zero-terminated) to OsPath
cassert(sizeof(wchar_t) == sizeof(WCHAR));
const size_t nameChars = fni->FileNameLength / sizeof(WCHAR);
const NativePath name(fni->FileName, nameChars);
const OsPath name(Path::String(fni->FileName, nameChars));
const NativePath pathname = Path::Join(Path(), name);
const OsPath pathname = m_path / name;
const DirWatchNotification::EType type = TypeFromAction(fni->Action);
notifications.push_back(DirWatchNotification(pathname, type));
@ -199,7 +199,7 @@ private:
}
}
NativePath m_path;
OsPath m_path;
DirHandle m_dirHandle;
// rationale:
@ -368,9 +368,9 @@ private:
class DirWatchManager
{
public:
LibError Add(const NativePath& path, PDirWatch& dirWatch)
LibError Add(const OsPath& path, PDirWatch& dirWatch)
{
debug_assert(Path::IsDirectory(path));
debug_assert(path.IsDirectory());
// 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
@ -378,7 +378,7 @@ public:
for(IntrusiveLink* link = m_sentinel.Next(); link != &m_sentinel; link = link->Next())
{
DirWatch* const existingDirWatch = (DirWatch*)(uintptr_t(link) - offsetof(DirWatch, link));
if(path_is_subpath(path.c_str(), existingDirWatch->request->Path().c_str()))
if(path_is_subpath(OsString(path).c_str(), OsString(existingDirWatch->request->Path()).c_str()))
{
dirWatch.reset(new DirWatch(&m_sentinel, existingDirWatch->request));
return INFO::OK;
@ -412,7 +412,7 @@ static DirWatchManager* s_dirWatchManager;
//-----------------------------------------------------------------------------
LibError dir_watch_Add(const NativePath& path, PDirWatch& dirWatch)
LibError dir_watch_Add(const OsPath& path, PDirWatch& dirWatch)
{
WinScopedLock lock(WDIR_WATCH_CS);
return s_dirWatchManager->Add(path, dirWatch);

View File

@ -43,18 +43,18 @@
//-----------------------------------------------------------------------------
static LibError ReadVersionString(const NativePath& modulePathname, wchar_t* out_ver, size_t out_ver_len)
static LibError ReadVersionString(const OsPath& modulePathname, wchar_t* out_ver, size_t out_ver_len)
{
WinScopedPreserveLastError s; // GetFileVersion*, Ver*
// determine size of and allocate memory for version information.
DWORD unused;
const DWORD ver_size = GetFileVersionInfoSizeW(modulePathname.c_str(), &unused); // [bytes]
const DWORD ver_size = GetFileVersionInfoSizeW(OsString(modulePathname).c_str(), &unused); // [bytes]
if(!ver_size)
{
// check if the failure is due to not finding modulePathname
// (necessary since GetFileVersionInfoSize doesn't SetLastError)
HMODULE hModule = LoadLibraryExW(modulePathname.c_str(), 0, LOAD_LIBRARY_AS_DATAFILE);
HMODULE hModule = LoadLibraryExW(OsString(modulePathname).c_str(), 0, LOAD_LIBRARY_AS_DATAFILE);
if(!hModule)
return ERR::FAIL; // NOWARN (file not found - due to FS redirection?)
FreeLibrary(hModule);
@ -62,7 +62,7 @@ static LibError ReadVersionString(const NativePath& modulePathname, wchar_t* out
}
shared_ptr<u8> mem = Allocate(ver_size);
if(!GetFileVersionInfoW(modulePathname.c_str(), 0, ver_size, mem.get()))
if(!GetFileVersionInfoW(OsString(modulePathname).c_str(), 0, ver_size, mem.get()))
WARN_RETURN(ERR::_3);
u16* lang; // -> 16 bit language ID, 16 bit codepage
@ -83,7 +83,7 @@ static LibError ReadVersionString(const NativePath& modulePathname, wchar_t* out
}
void wdll_ver_Append(const NativePath& pathname, VersionList& list)
void wdll_ver_Append(const OsPath& pathname, VersionList& list)
{
if(pathname.empty())
return; // avoid error in ReadVersionString
@ -91,10 +91,10 @@ void wdll_ver_Append(const NativePath& pathname, VersionList& list)
// pathname may not have an extension (e.g. driver names from the
// registry). note that always appending ".dll" would be incorrect
// since some have ".sys" extension.
NativePath modulePathname(pathname);
if(Path::Extension(modulePathname).empty())
modulePathname = Path::ChangeExtension(modulePathname, L".dll");
const NativePath moduleName(Path::Filename(modulePathname));
OsPath modulePathname(pathname);
if(modulePathname.Extension() == "")
modulePathname = modulePathname.ChangeExtension(L".dll");
const OsPath moduleName(modulePathname.Filename());
// read file version. try this with and without FS redirection since
// pathname might assume both.
@ -112,7 +112,7 @@ void wdll_ver_Append(const NativePath& pathname, VersionList& list)
if(!list.empty())
list += L", ";
list += moduleName;
list += moduleName.Filename().string();
list += L" (";
list += versionString;
list += L")";

View File

@ -41,6 +41,6 @@ typedef std::wstring VersionList;
* The text output includes the module name.
* On failure, the version is given as "unknown".
**/
extern void wdll_ver_Append(const NativePath& pathname, VersionList& list);
extern void wdll_ver_Append(const OsPath& pathname, VersionList& list);
#endif // #ifndef INCLUDED_WDLL_VER

View File

@ -139,7 +139,7 @@ static DWORD CreationDisposition(int oflag)
// (re)open file in asynchronous mode and associate handle with fd.
// (this works because the files default to DENY_NONE sharing)
LibError waio_reopen(int fd, const wchar_t* pathname, int oflag, ...)
LibError waio_reopen(int fd, const OsPath& pathname, int oflag, ...)
{
WinScopedPreserveLastError s; // CreateFile
@ -176,7 +176,7 @@ LibError waio_reopen(int fd, const wchar_t* pathname, int oflag, ...)
// open file
const DWORD create = CreationDisposition(oflag);
const HANDLE hFile = CreateFileW(pathname, access, share, 0, create, FILE_ATTRIBUTE_NORMAL|flags, 0);
const HANDLE hFile = CreateFileW(OsString(pathname).c_str(), access, share, 0, create, FILE_ATTRIBUTE_NORMAL|flags, 0);
if(hFile == INVALID_HANDLE_VALUE)
return LibError_from_GLE();

View File

@ -27,12 +27,12 @@
#ifndef INCLUDED_WAIO
#define INCLUDED_WAIO
#include "lib/lib_errors.h"
#include "lib/native_path.h"
#include "lib/sysdep/os/win/wposix/wposix_types.h"
#include "lib/sysdep/os/win/wposix/no_crt_posix.h"
#include "lib/lib_errors.h"
// Note: transfer buffers, offsets, and lengths must be sector-aligned
// (we don't bother copying to an align buffer because the file cache
// already requires splitting IOs into aligned blocks)
@ -115,7 +115,7 @@ extern int lio_listio(int, struct aiocb* const[], int, struct sigevent*);
// (re)open file in asynchronous mode and associate handle with fd.
// (this works because the files default to DENY_NONE sharing)
extern LibError waio_reopen(int fd, const wchar_t* pathname, int oflag, ...);
extern LibError waio_reopen(int fd, const OsPath& pathname, int oflag, ...);
extern LibError waio_close(int fd);
#endif // #ifndef INCLUDED_WAIO

View File

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

View File

@ -190,9 +190,9 @@ static inline void wdir_free(WDIR* d)
static const DWORD hs = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
// make sure path exists and is a normal (according to attributes) directory.
static bool is_normal_dir(const wchar_t* path)
static bool is_normal_dir(const OsPath& path)
{
const DWORD fa = GetFileAttributesW(path);
const DWORD fa = GetFileAttributesW(OsString(path).c_str());
// path not found
if(fa == INVALID_FILE_ATTRIBUTES)
@ -213,7 +213,7 @@ static bool is_normal_dir(const wchar_t* path)
}
WDIR* wopendir(const wchar_t* path)
WDIR* wopendir(const OsPath& path)
{
if(!is_normal_dir(path))
{
@ -228,16 +228,14 @@ WDIR* wopendir(const wchar_t* path)
return 0;
}
// build search path for FindFirstFileW. note: "path\\dir" only returns
// information about that directory; trailing slashes aren't allowed.
// for dir entries to be returned, we have to append "\\*".
wchar_t search_path[PATH_MAX];
swprintf_s(search_path, ARRAY_SIZE(search_path), L"%ls\\*", path);
// NB: c:\path only returns information about that directory; trailing
// slashes aren't allowed. append * to retrieve directory entries.
OsPath searchPath = path/"*";
// note: we could store search_path and defer FindFirstFileW until
// wreaddir. this way is a bit more complex but required for
// correctness (we must return a valid DIR iff <path> is valid).
d->hFind = FindFirstFileW(search_path, &d->fd);
d->hFind = FindFirstFileW(OsString(searchPath).c_str(), &d->fd);
if(d->hFind == INVALID_HANDLE_VALUE)
{
// not an error - the directory is just empty.
@ -327,13 +325,13 @@ int wclosedir(WDIR* d)
// fcntl.h
//-----------------------------------------------------------------------------
int wopen(const wchar_t* pathname, int oflag)
int wopen(const OsPath& pathname, int oflag)
{
debug_assert(!(oflag & O_CREAT));
return wopen(pathname, oflag, _S_IREAD|_S_IWRITE);
return wopen(OsString(pathname).c_str(), oflag, _S_IREAD|_S_IWRITE);
}
int wopen(const wchar_t* pathname, int oflag, mode_t mode_arg)
int wopen(const OsPath& pathname, int oflag, mode_t mode_arg)
{
mode_t mode = _S_IREAD|_S_IWRITE;
if(oflag & O_CREAT)
@ -341,7 +339,7 @@ int wopen(const wchar_t* pathname, int oflag, mode_t mode_arg)
WinScopedPreserveLastError s; // _wsopen_s's CreateFileW
int fd;
errno_t ret = _wsopen_s(&fd, pathname, oflag, _SH_DENYNO, mode);
errno_t ret = _wsopen_s(&fd, OsString(pathname).c_str(), oflag, _SH_DENYNO, mode);
if(ret != 0)
{
errno = ret;
@ -376,9 +374,9 @@ int wclose(int fd)
// unistd.h
//-----------------------------------------------------------------------------
int wtruncate(const wchar_t* pathname, off_t length)
int wtruncate(const OsPath& pathname, off_t length)
{
HANDLE hFile = CreateFileW(pathname, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
HANDLE hFile = CreateFileW(OsString(pathname).c_str(), GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
debug_assert(hFile != INVALID_HANDLE_VALUE);
LARGE_INTEGER ofs; ofs.QuadPart = length;
WARN_IF_FALSE(SetFilePointerEx(hFile, ofs, 0, FILE_BEGIN));
@ -388,28 +386,29 @@ int wtruncate(const wchar_t* pathname, off_t length)
}
int wunlink(const wchar_t* pathname)
int wunlink(const OsPath& pathname)
{
return _wunlink(pathname);
return _wunlink(OsString(pathname).c_str());
}
int wrmdir(const wchar_t* path)
int wrmdir(const OsPath& path)
{
return _wrmdir(path);
return _wrmdir(OsString(path).c_str());
}
int wrename(const wchar_t* pathnameOld, const wchar_t* pathnameNew)
int wrename(const OsPath& pathnameOld, const OsPath& pathnameNew)
{
return _wrename(pathnameOld, pathnameNew);
return _wrename(OsString(pathnameOld).c_str(), OsString(pathnameNew).c_str());
}
wchar_t* wrealpath(const wchar_t* pathname, wchar_t* resolved)
OsPath wrealpath(const OsPath& pathname)
{
if(!GetFullPathNameW(pathname, PATH_MAX, resolved, 0))
return 0;
wchar_t resolved[PATH_MAX];
if(!GetFullPathNameW(OsString(pathname).c_str(), PATH_MAX, resolved, 0))
return OsPath();
return resolved;
}
@ -433,9 +432,9 @@ static int ErrnoFromCreateDirectory()
}
}
int wmkdir(const wchar_t* path, mode_t UNUSED(mode))
int wmkdir(const OsPath& path, mode_t UNUSED(mode))
{
if(!CreateDirectoryW(path, (LPSECURITY_ATTRIBUTES)NULL))
if(!CreateDirectoryW(OsString(path).c_str(), (LPSECURITY_ATTRIBUTES)NULL))
{
errno = ErrnoFromCreateDirectory();
return -1;
@ -445,7 +444,7 @@ int wmkdir(const wchar_t* path, mode_t UNUSED(mode))
}
int wstat(const wchar_t* pathname, struct stat* buf)
int wstat(const OsPath& pathname, struct stat* buf)
{
return _wstat64(pathname, buf);
return _wstat64(OsString(pathname).c_str(), buf);
}

View File

@ -1478,7 +1478,7 @@ void SDL_Quit()
}
static NativePath GetStdoutPathname()
static OsPath GetStdoutPathname()
{
// the current directory is unreliable, so use the full path to
// the current executable.
@ -1489,7 +1489,7 @@ static NativePath GetStdoutPathname()
// add the EXE name to the filename to allow multiple executables
// with their own redirections. (we can't use wutil_ExecutablePath
// because it doesn't return the basename)
NativePath pathname = Path::ChangeExtension(NativePath(pathnameEXE), L"_stdout.txt");
OsPath pathname = OsPath(pathnameEXE).ChangeExtension(L"_stdout.txt");
return pathname;
}
@ -1500,7 +1500,7 @@ static void RedirectStdout()
if(wutil_IsValidHandle(GetStdHandle(STD_OUTPUT_HANDLE)))
return;
const NativePath pathname = GetStdoutPathname();
const OsPath pathname = GetStdoutPathname();
// ignore BoundsChecker warnings here. subsystem is set to "Windows"
// to prevent the OS from opening a console on startup (ugly).
@ -1509,7 +1509,7 @@ static void RedirectStdout()
FILE* f = 0;
// (return value ignored - it indicates 'file already exists' even
// if f is valid)
(void)_wfreopen_s(&f, pathname.c_str(), L"wt", stdout);
(void)_wfreopen_s(&f, OsString(pathname).c_str(), L"wt", stdout);
// executable directory (probably Program Files) is read-only for
// non-Administrators. we can't pick another directory because
// ah_log_dir might not be valid until the app's init has run,

View File

@ -40,27 +40,27 @@
#include "lib/sysdep/os/win/wmi.h"
static bool IsOpenAlDllName(const NativePath& name)
static bool IsOpenAlDllName(const Path::String& name)
{
// (matches "*oal.dll" and "*OpenAL*", as with OpenAL router's search)
return name.find(L"oal.dll") != NativePath::npos || name.find(L"OpenAL") != NativePath::npos;
return name.find(L"oal.dll") != Path::String::npos || name.find(L"OpenAL") != Path::String::npos;
}
// ensures each OpenAL DLL is only listed once (even if present in several
// directories on our search path).
typedef std::set<NativePath> StringSet;
typedef std::set<Path::String> StringSet;
// find all OpenAL DLLs in a dir.
// call in library search order (exe dir, then win sys dir); otherwise,
// DLLs in the executable's starting directory hide those of the
// same name in the system directory.
static void add_oal_dlls_in_dir(const NativePath& path, StringSet& dlls, VersionList& versionList)
static void add_oal_dlls_in_dir(const OsPath& path, StringSet& dlls, VersionList& versionList)
{
FileInfos files;
(void)GetDirectoryEntries(path, &files, 0);
for(size_t i = 0; i < files.size(); i++)
{
const NativePath name = files[i].Name();
const Path::String name = files[i].Name().string();
if(!IsOpenAlDllName(name))
continue;
@ -69,7 +69,7 @@ static void add_oal_dlls_in_dir(const NativePath& path, StringSet& dlls, Version
if(!ret.second) // insert failed - element already there
continue;
wdll_ver_Append(Path::Join(path, name), versionList);
wdll_ver_Append(path / name, versionList);
}
}
@ -86,7 +86,7 @@ static void add_oal_dlls_in_dir(const NativePath& path, StringSet& dlls, Version
// the version info for that bogus driver path, we'll skip this code there.
// (delay-loading dsound.dll eliminates any overhead)
static NativePath directSoundDriverPath;
static OsPath directSoundDriverPath;
// store sound card name and path to DirectSound driver.
// called for each DirectSound driver, but aborts after first valid driver.
@ -99,14 +99,14 @@ static BOOL CALLBACK DirectSoundCallback(void* guid, const wchar_t* UNUSED(descr
// note: $system\\drivers is not in LoadLibrary's search list,
// so we have to give the full pathname.
directSoundDriverPath = Path::Join(Path::Join(wutil_SystemPath(), "drivers"), NativePath(module));
directSoundDriverPath = wutil_SystemPath()/"drivers" / module;
// we assume the first "driver name" (sound card) is the one we want;
// stick with that and stop calling.
return FALSE;
}
static const NativePath& GetDirectSoundDriverPath()
static const OsPath& GetDirectSoundDriverPath()
{
#define DS_OK 0
typedef BOOL (CALLBACK* LPDSENUMCALLBACKW)(void*, const wchar_t*, const wchar_t*, void*);

View File

@ -363,7 +363,7 @@ LibError sys_error_description_r(int user_err, wchar_t* buf, size_t max_chars)
}
LibError sys_get_module_filename(void* addr, NativePath& pathname)
LibError sys_get_module_filename(void* addr, OsPath& pathname)
{
MEMORY_BASIC_INFORMATION mbi;
const SIZE_T bytesWritten = VirtualQuery(addr, &mbi, sizeof(mbi));
@ -382,7 +382,7 @@ LibError sys_get_module_filename(void* addr, NativePath& pathname)
}
LibError sys_get_executable_name(NativePath& pathname)
LibError sys_get_executable_name(OsPath& pathname)
{
wchar_t pathnameBuf[MAX_PATH+1];
const DWORD charsWritten = GetModuleFileNameW(0, pathnameBuf, (DWORD)ARRAY_SIZE(pathnameBuf));
@ -418,21 +418,19 @@ static int CALLBACK BrowseCallback(HWND hWnd, unsigned int msg, LPARAM UNUSED(lP
return 0;
}
LibError sys_pick_directory(NativePath& path)
LibError sys_pick_directory(OsPath& path)
{
// (must not use multi-threaded apartment due to BIF_NEWDIALOGSTYLE)
const HRESULT hr = CoInitialize(0);
debug_assert(hr == S_OK || hr == S_FALSE); // S_FALSE == already initialized
// NB: BFFM_SETSELECTIONW can't deal with '/' separators
const NativePath initialPath = path;
// note: bi.pszDisplayName isn't the full path, so it isn't of any use.
BROWSEINFOW bi;
memset(&bi, 0, sizeof(bi));
bi.ulFlags = BIF_RETURNONLYFSDIRS|BIF_NEWDIALOGSTYLE|BIF_NONEWFOLDERBUTTON;
// for setting starting directory:
bi.lpfn = (BFFCALLBACK)BrowseCallback;
const Path::String initialPath = OsString(path); // NB: BFFM_SETSELECTIONW can't deal with '/' separators
bi.lParam = (LPARAM)initialPath.c_str();
const LPITEMIDLIST pidl = SHBrowseForFolderW(&bi);
if(!pidl) // user canceled
@ -597,3 +595,11 @@ done:
}
#endif
FILE* sys_OpenFile(const OsPath& pathname, const char* mode)
{
FILE* f = 0;
const std::wstring wmode(mode, mode+strlen(mode));
(void)_wfopen_s(&f, OsString(pathname).c_str(), wmode.c_str());
return f;
}

View File

@ -267,30 +267,30 @@ bool wutil_HasCommandLineArgument(const wchar_t* arg)
//-----------------------------------------------------------------------------
// directories
NativePath wutil_DetectExecutablePath()
OsPath wutil_DetectExecutablePath()
{
wchar_t modulePathname[MAX_PATH+1] = {0};
const DWORD len = GetModuleFileNameW(GetModuleHandle(0), modulePathname, MAX_PATH);
debug_assert(len != 0);
return Path::Path(NativePath(modulePathname));
return OsPath(modulePathname).Parent();
}
// (NB: wutil_Init is called before static ctors => use placement new)
static NativePath* systemPath;
static NativePath* executablePath;
static NativePath* appdataPath;
static OsPath* systemPath;
static OsPath* executablePath;
static OsPath* appdataPath;
const NativePath& wutil_SystemPath()
const OsPath& wutil_SystemPath()
{
return *systemPath;
}
const NativePath& wutil_ExecutablePath()
const OsPath& wutil_ExecutablePath()
{
return *executablePath;
}
const NativePath& wutil_AppdataPath()
const OsPath& wutil_AppdataPath()
{
return *appdataPath;
}
@ -305,11 +305,11 @@ static void GetDirectories()
{
const UINT charsWritten = GetSystemDirectoryW(path, MAX_PATH);
debug_assert(charsWritten != 0);
systemPath = new(wutil_Allocate(sizeof(NativePath))) NativePath(path);
systemPath = new(wutil_Allocate(sizeof(OsPath))) OsPath(path);
}
// executable's directory
executablePath = new(wutil_Allocate(sizeof(NativePath))) NativePath(wutil_DetectExecutablePath());
executablePath = new(wutil_Allocate(sizeof(OsPath))) OsPath(wutil_DetectExecutablePath());
// application data
{
@ -317,18 +317,18 @@ static void GetDirectories()
HANDLE token = 0;
const HRESULT ret = SHGetFolderPathW(hwnd, CSIDL_APPDATA, token, 0, path);
debug_assert(SUCCEEDED(ret));
appdataPath = new(wutil_Allocate(sizeof(NativePath))) NativePath(path);
appdataPath = new(wutil_Allocate(sizeof(OsPath))) OsPath(path);
}
}
static void FreeDirectories()
{
systemPath->~NativePath();
systemPath->~OsPath();
wutil_Free(systemPath);
executablePath->~NativePath();
executablePath->~OsPath();
wutil_Free(executablePath);
appdataPath->~NativePath();
appdataPath->~OsPath();
wutil_Free(appdataPath);
}

View File

@ -170,11 +170,11 @@ extern bool wutil_HasCommandLineArgument(const wchar_t* arg);
// used by wutil_ExecutablePath, but provided in case other code
// needs to know this before our wutil_Init runs.
extern NativePath wutil_DetectExecutablePath();
extern OsPath wutil_DetectExecutablePath();
extern const NativePath& wutil_SystemPath();
extern const NativePath& wutil_ExecutablePath();
extern const NativePath& wutil_AppdataPath();
extern const OsPath& wutil_SystemPath();
extern const OsPath& wutil_ExecutablePath();
extern const OsPath& wutil_AppdataPath();
//-----------------------------------------------------------------------------

View File

@ -111,7 +111,7 @@ extern LibError sys_error_description_r(int err, wchar_t* buf, size_t max_chars)
*
* note: this is useful for handling exceptions in other modules.
**/
LibError sys_get_module_filename(void* addr, NativePath& pathname);
LibError sys_get_module_filename(void* addr, OsPath& pathname);
/**
* Get path to the current executable.
@ -121,7 +121,7 @@ LibError sys_get_module_filename(void* addr, NativePath& pathname);
*
* this is useful for determining installation directory, e.g. for VFS.
**/
LIB_API LibError sys_get_executable_name(NativePath& pathname);
LIB_API LibError sys_get_executable_name(OsPath& pathname);
/**
* Get the current user's login name.
@ -137,7 +137,7 @@ extern std::wstring sys_get_user_name();
* faster browsing. if INFO::OK is returned, it receives
* chosen directory path.
**/
extern LibError sys_pick_directory(NativePath& path);
extern LibError sys_pick_directory(OsPath& path);
/**
* Open the user's default web browser to the given URL.
@ -185,6 +185,8 @@ LIB_API LibError sys_generate_random_bytes(u8* buf, size_t count);
**/
LIB_API LibError sys_get_proxy_config(const std::wstring& url, std::wstring& proxy);
LIB_API FILE* sys_OpenFile(const OsPath& pathname, const char* mode);
/**
* directory separation character
**/

View File

@ -27,6 +27,7 @@
#include "lib/secure_crt.h"
#include "lib/utf8.h"
#include "lib/sysdep/cpu.h"
#include "lib/sysdep/filesystem.h"
#include "lib/sysdep/sysdep.h"
#if OS_LINUX
@ -49,16 +50,16 @@ public:
void test_sys_get_executable_name()
{
NativePath path;
OsPath path;
// Try it first with the real executable (i.e. the
// one that's running this test code)
TS_ASSERT_EQUALS(sys_get_executable_name(path), INFO::OK);
// Check it's absolute
TSM_ASSERT(L"Path: "+path, path_is_absolute(path.c_str()));
TSM_ASSERT(L"Path: "+path.string(), path_is_absolute(path.string().c_str()));
// Check the file exists
struct stat s;
TSM_ASSERT_EQUALS(L"Path: "+path, wstat(path.c_str(), &s), 0);
TSM_ASSERT_EQUALS(L"Path: "+path.string(), wstat(path, &s), 0);
// Do some platform-specific tests, based on the
// implementations of sys_get_executable_name:
@ -78,7 +79,7 @@ public:
TS_ASSERT(realpath(root, rootres));
std::string rootstr(rootres);
std::wstring rootstrw(wstring_from_utf8(rootstr));
OsPath rootstrw(rootstr);
const char* dirs[] = {
"/example",
@ -111,12 +112,12 @@ public:
{
Mock_dladdr d(rootstr+"/example/executable");
TS_ASSERT_EQUALS(sys_get_executable_name(path), INFO::OK);
TS_ASSERT_WSTR_EQUALS(path, rootstrw+L"/example/executable");
TS_ASSERT_PATH_EQUALS(path, rootstrw/L"example/executable");
}
{
Mock_dladdr d(rootstr+"/example/./a/b/../e/../../executable");
TS_ASSERT_EQUALS(sys_get_executable_name(path), INFO::OK);
TS_ASSERT_WSTR_EQUALS(path, rootstrw+L"/example/executable");
TS_ASSERT_PATH_EQUALS(path, rootstrw/L"example/executable");
}
// Try with relative paths
@ -124,19 +125,19 @@ public:
Mock_dladdr d("./executable");
Mock_getcwd m(rootstr+"/example");
TS_ASSERT_EQUALS(sys_get_executable_name(path), INFO::OK);
TS_ASSERT_WSTR_EQUALS(path, rootstrw+L"/example/executable");
TS_ASSERT_PATH_EQUALS(path, rootstrw/L"example/executable");
}
{
Mock_dladdr d("./executable");
Mock_getcwd m(rootstr+"/example/");
TS_ASSERT_EQUALS(sys_get_executable_name(path), INFO::OK);
TS_ASSERT_WSTR_EQUALS(path, rootstrw+L"/example/executable");
TS_ASSERT_PATH_EQUALS(path, rootstrw/L"example/executable");
}
{
Mock_dladdr d("../d/../../f/executable");
Mock_getcwd m(rootstr+"/example/a/b/c");
TS_ASSERT_EQUALS(sys_get_executable_name(path), INFO::OK);
TS_ASSERT_WSTR_EQUALS(path, rootstrw+L"/example/a/f/executable");
TS_ASSERT_PATH_EQUALS(path, rootstrw/L"example/a/f/executable");
}
// Try with pathless names

View File

@ -566,7 +566,7 @@ bool tex_is_known_extension(const VfsPath& pathname)
{
const TexCodecVTbl* dummy;
// found codec for it => known extension
const NativePath extension = Path::Extension(pathname);
const OsPath extension = pathname.Extension();
if(tex_codec_for_filename(extension, &dummy) == INFO::OK)
return true;
@ -699,7 +699,7 @@ size_t tex_hdr_size(const VfsPath& filename)
{
const TexCodecVTbl* c;
const NativePath extension = Path::Extension(filename);
const OsPath extension = filename.Extension();
CHECK_ERR(tex_codec_for_filename(extension, &c));
return c->hdr_size(0);
}
@ -751,7 +751,7 @@ LibError tex_decode(const shared_ptr<u8>& data, size_t data_size, Tex* t)
}
LibError tex_encode(Tex* t, const NativePath& extension, DynArray* da)
LibError tex_encode(Tex* t, const OsPath& extension, DynArray* da)
{
CHECK_TEX(t);
CHECK_ERR(tex_validate_plain_format(t->bpp, t->flags));

View File

@ -105,6 +105,7 @@ library and IO layer. Read and write are zero-copy.
#define INCLUDED_TEX
#include "lib/res/handle.h"
#include "lib/native_path.h"
#include "lib/file/vfs/vfs_path.h"
#include "lib/allocators/dynarray.h"
@ -290,7 +291,7 @@ extern LibError tex_decode(const shared_ptr<u8>& data, size_t data_size, Tex* t)
* when no longer needed. Invalid unless function succeeds.
* @return LibError
**/
extern LibError tex_encode(Tex* t, const NativePath& extension, DynArray* da);
extern LibError tex_encode(Tex* t, const OsPath& extension, DynArray* da);
/**
* store the given image data into a Tex object; this will be as if

View File

@ -74,9 +74,9 @@ static bool bmp_is_hdr(const u8* file)
}
static bool bmp_is_ext(const NativePath& extension)
static bool bmp_is_ext(const OsPath& extension)
{
return !wcscasecmp(extension.c_str(), L".bmp");
return extension == L".bmp";
}

View File

@ -63,7 +63,7 @@ void tex_codec_unregister_all()
// or return ERR::TEX_UNKNOWN_FORMAT if unknown.
// note: does not raise a warning because it is used by
// tex_is_known_extension.
LibError tex_codec_for_filename(const NativePath& extension, const TexCodecVTbl** c)
LibError tex_codec_for_filename(const OsPath& extension, const TexCodecVTbl** c)
{
for(*c = codecs; *c; *c = (*c)->next)
{

View File

@ -96,7 +96,7 @@ struct TexCodecVTbl
* @param extension (including '.')
* @return bool
**/
bool (*is_ext)(const NativePath& extension);
bool (*is_ext)(const OsPath& extension);
/**
* return size of the file header supported by this codec.
@ -170,7 +170,7 @@ extern int tex_codec_register(TexCodecVTbl* c);
* called by tex_is_known_extension) if no codec indicates they can
* handle the given extension.
**/
extern LibError tex_codec_for_filename(const NativePath& extension, const TexCodecVTbl** c);
extern LibError tex_codec_for_filename(const OsPath& extension, const TexCodecVTbl** c);
/**
* find codec that recognizes the header's magic field.

View File

@ -579,9 +579,9 @@ static bool dds_is_hdr(const u8* file)
}
static bool dds_is_ext(const NativePath& extension)
static bool dds_is_ext(const OsPath& extension)
{
return !wcscasecmp(extension.c_str(), L".dds");
return extension == L".dds";
}

View File

@ -573,9 +573,9 @@ static bool jpg_is_hdr(const u8* file)
}
static bool jpg_is_ext(const NativePath& extension)
static bool jpg_is_ext(const OsPath& extension)
{
return !wcscasecmp(extension.c_str(), L".jpg") || !wcscasecmp(extension.c_str(), L".jpeg");
return extension == L".jpg" || extension == L".jpeg";
}

View File

@ -183,9 +183,9 @@ static bool png_is_hdr(const u8* file)
}
static bool png_is_ext(const NativePath& extension)
static bool png_is_ext(const OsPath& extension)
{
return !wcscasecmp(extension.c_str(), L".png");
return extension == L".png";
}

Some files were not shown because too many files have changed in this diff Show More