khanat-opennel-code/code/nel/include/nel/misc/path.h

729 lines
30 KiB
C++

// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef NL_PATH_H
#define NL_PATH_H
#include "types_nl.h"
#include "time_nl.h"
#include <map>
#include <string>
#include <vector>
#include "common.h"
#include "string_mapper.h"
namespace NLMISC {
/// Exception throw when a find is not found in a lookup() call
struct EPathNotFound : public Exception
{
EPathNotFound (const std::string& filename) : Exception ("Path not found for " + filename) { }
};
/** Utility to store a pre-built list of file, bnp and xml_pack
* Used by CPath to store the default application patch.
* Can be used by user to build a custom set of file.
* \warning addSearchPath(), clearMap() and remapExtension() are not reentrant.
* \warning all path and files are *case sensitive* on linux.
*/
class CFileContainer
{
// no copy allowed
CFileContainer(const CFileContainer &/* other */)
{}
CFileContainer &operator =(const CFileContainer &/* other */)
{
return *this;
}
public:
CFileContainer()
{
_MemoryCompressed = false;
_AllFileNames = NULL;
}
~CFileContainer();
void addSearchPath (const std::string &path, bool recurse, bool alternative, class IProgressCallback *progressCallBack = NULL);
/** Used only for compatibility with the old CPath. In this case, we don't use the map to have the same behavior as the old CPath */
void addSearchPath (const std::string &path) { addSearchPath (path, false, true, NULL); }
/** Same as AddSearchPath but with a file "c:/autoexec.bat" this file only will included. wildwards *doesn't* work */
void addSearchFile (const std::string &file, bool remap = false, const std::string &virtual_ext = "", class NLMISC::IProgressCallback *progressCallBack = NULL);
/** Same as AddSearchPath but with a path file "c:/test.pth" all files name contain in this file will be included (the extention is used to know that it's a path file) */
void addSearchListFile (const std::string &filename, bool recurse, bool alternative);
/** Same as AddSearchPath but with a big file "c:/test.nbf" all files name contained in the big file will be included (the extention (Nel Big File) is used to know that it's a big file) */
void addSearchBigFile (const std::string &filename, bool recurse, bool alternative, class NLMISC::IProgressCallback *progressCallBack = NULL);
/** Same as AddSearchPath but with a xml pack file "c:/test.xml_pack" all files name contained in the xml pack will be included */
void addSearchXmlpackFile (const std::string &sXmlpackFilename, bool recurse, bool alternative, class NLMISC::IProgressCallback *progressCallBack = NULL);
/** Remove all search path contains in the alternative directories */
void removeAllAlternativeSearchPath ();
// Remove a set of big file from the search paths (and also from CBigFile)
void removeBigFiles(const std::vector<std::string> &bnpFilenames);
/** Returns the long name (path + filename) for the specified file.
* The directory separator is always '/'.
* First, the lookup() lookups in standard directories (Alternative=false).
* If not found, it lookups in the Alternative directories.
* If not found the lookup() returns empty string "" (and generate an exception if throwException is true)
*
* The filename is not case sensitive so if the real filename is "FooBAR.Jpg" and you call lookup("fOOBar.jPg"), it'll
* return the real filename "FooBAR.Jpg"
*
* \param filename the file name you are seeking. (ex: "test.txt")
* \param throwException used for backward compatibility, set to true to generate an EPathNotFound.
* \param displayWarning set to false if you don't want the function displays a warning if the file is not found
* \param lookupInLocalDirectory if true, the lookup() will first try to open the file without path.
* \return empty string if file is not found or the full path + file name (ex: "c:/temp/test.txt");
*
* ***********************************************
* WARNING: This Method is NOT thread safe
* user must ensure that no mutator is called on CPath while async loading
* ***********************************************
*
*/
std::string lookup (const std::string &filename, bool throwException = true, bool displayWarning = true, bool lookupInLocalDirectory = true);
/** Return if a file is present in the lookup map.
* The function changes filename into lower case and removes ended spaces before searching.
*
* \warning This function checks *only* in the map, not in local dir or alternative dir
*
* \param filename the file name you are seeking. (ex: "test.txt")
* \param lookupInLocalDirectory if true, the lookup() will first try to open the file without path.
* \return true if the filename exists in the map used by lookup to know where the file is, false otherwise
*/
bool exists (const std::string &filename);
/** Clears the map that contains all cached files (Use this function to take into account new files).
*/
void clearMap ();
/** Add a remapping function to allow file extension substitution.
* - eg remapExtension("dds", "tga", true) Where the boolean indicates whether
* the "dds" should replace a "tga" if one exists - again - a warning should
* be generated if the two are present.
*
* ie: If you have a file called pic.dds and you call remapExtension("dds", "tga", true),
* if you call lookup("pic.tga"), it'll return "pic.dds"
*
*/
void remapExtension (const std::string &ext1, const std::string &ext2, bool substitute);
/** Add file remapping
* ie: If you have a file called pic.dds, and call remapFile("picture.dds", "pic.dds")
* calling lookup("picture.dds") will in fact call lookup("pic.dds")
*/
void remapFile (const std::string &file1, const std::string &file2);
/** Load a file containing the remapped file (you must have done addsearchpath, this method use lookup)
* Format is remapped_name_file, real_file
* separators are , and \n
*/
void loadRemappedFiles (const std::string &file);
void display ();
/** Take a path and put it in the portable format and add a terminated / if needed
* ie: "C:\\Game/dir1" will become "C:/Game/dir1/" or "C:/Game/dir1" if addFinalSlash is false
*/
std::string standardizePath (const std::string &path, bool addFinalSlash = true);
/** Replace / with \ for dos process. Use only this function if can't do another way.
* For example, if you do a system("copy data/toto data/tata"); it'll not work because dos doesn't
* understand /.
* But in the majority of case, / working (it works for fopen for example)
*/
std::string standardizeDosPath (const std::string &path);
/** List all files in a directory.
* \param path path where files are scanned. No-op if empty
* \param recurse true if want to recurs directories
* \param wantDir true if want to add directories in result
* \param wantFile true if want to add files in result
* \param result list of string where directories/files names are added.
* \param progressCallBack is a progression callback interface pointer.
* \param showEverything false skips *.log files and CVS directories
*/
void getPathContent (const std::string &path, bool recurse, bool wantDir, bool wantFile, std::vector<std::string> &result, class IProgressCallback *progressCallBack = NULL, bool showEverything=false);
/** Get the full path based on a file/path and the current directory. Example, imagine that the current path is c:\temp and toto is a directory
* getFullPath ("toto") returns "c:/temp/toto/"
* getFullPath ("../toto") returns "c:/temp/../toto/"
* getFullPath ("d:\dir\toto") returns "d:/dir/toto/"
* getFullPath ("\toto") returns "c:/toto/"
* getFullPath ("") returns "c:/temp/"
*
* \param path the path
* \return the full path
*/
std::string getFullPath (const std::string &path, bool addFinalSlash = true);
/** Returns the current path of the application.
*/
std::string getCurrentPath ();
/** Set the current path of the application.
*/
bool setCurrentPath (const std::string &path);
/** Create a list of file having the requested extension.
*/
void getFileList(const std::string &extension, std::vector<std::string> &filenames);
/** Create a list of file having the requested string in the filename and the requested extension.
*/
void getFileListByName(const std::string &extension, const std::string &name, std::vector<std::string> &filenames);
/** Make a path relative to another if possible, else doesn't change it.
* \param basePath is the base path to be relative to.
* \param relativePath is the path to make relative to basePath.
* return true if relativePath as been done relative to basePath, false is relativePath has not been changed.
*/
bool makePathRelative (const char *basePath, std::string &relativePath);
/** If File in this list is added more than one in an addSearchPath, it doesn't launch a warning.
*/
void addIgnoredDoubleFile(const std::string &ignoredFile);
/** For the moment after memoryCompress you cant addsearchpath anymore
*/
void memoryCompress();
void memoryUncompress();
bool isMemoryCompressed() { return _MemoryCompressed; }
/** Get the ms windows directory (in standardized way with end slash), or returns an empty string on other os
*/
std::string getWindowsDirectory();
/** Get application directory.
* \return directory where applications should write files.
*/
std::string getApplicationDirectory(const std::string &appName = "");
/** Get a temporary directory.
* \return temporary directory where applications should write files.
*/
std::string getTemporaryDirectory();
private:
// All path in this vector must have a terminated '/'
std::vector<std::string> _AlternativePaths;
std::vector<std::string> IgnoredFiles;
std::map<std::string, std::string> _RemappedFiles;
// ----------------------------------------------
// MEMORY WISE
// ----------------------------------------------
bool _MemoryCompressed;
CStaticStringMapper SSMext;
CStaticStringMapper SSMpath;
// If NOT memory compressed use this
// ---------------------------------
struct CFileEntry
{
std::string Name; // Normal case
uint32 idPath : 16;
uint32 idExt : 15;
uint32 Remapped : 1;
};
typedef std::map<std::string, CFileEntry> TFiles;
TFiles _Files; // first is the filename in lowercase (can be with a remapped extension)
// If memory compressed use this
// -----------------------------
struct CMCFileEntry
{
char *Name; // Normal case (the search is done by using nlstricmp)
uint32 idPath : 16; // Path (not with file at the end) - look in the SSMpath (65536 different path allowed)
uint32 idExt : 15; // real extension of the file if remapped - look in the SSMext (32768 different extension allowed)
uint32 Remapped : 1; // true if the file is remapped
};
char *_AllFileNames;
// first is the filename that can be with a remapped extension
std::vector<CMCFileEntry> _MCFiles;
// Compare a MCFileEntry with a lowered string (useful for MCfind)
class CMCFileComp
{
public:
sint specialCompare(const CMCFileEntry &fe, const char *rhs)
{
char *lhs = fe.Name;
uint8 lchar, rchar;
while (*lhs != '\0' && *rhs != '\0')
{
// lower case compare because name is in normal case
lchar = uint8(::tolower(*lhs));
rchar = uint8(::tolower(*rhs));
if (lchar != rchar) return ((sint)lchar) - ((sint)rchar);
++lhs;
++rhs;
}
if (*lhs != 0) return 1;
if (*rhs != 0) return -1;
return 0;
}
bool operator()( const CMCFileEntry &fe, const CMCFileEntry &rhs )
{
return specialCompare( fe, rhs.Name ) < 0;
}
};
/// first ext1, second ext2 (ext1 could replace ext2)
std::vector<std::pair<std::string, std::string> > _Extensions;
CMCFileEntry *MCfind (const std::string &filename);
sint findExtension (const std::string &ext1, const std::string &ext2);
void insertFileInMap (const std::string &filename, const std::string &filepath, bool remap, const std::string &extension);
};
/**
* Utility class for searching files in different paths.
*
* Change in jun 2007 : now the implementation code is in CFileContainer, the
* CPath class is just a wrapper class that contains one instance of CFileContainer.
*
* \warning addSearchPath(), clearMap() and remapExtension() are not reentrant.
* \warning all path and files are *case sensitive* on linux.
* \author Vianney Lecroart
* \author Nevrax France
* \date 2001
*/
class CPath
{
NLMISC_SAFE_SINGLETON_DECL_PTR(CPath);
public:
/** Adds a search path.
* The path is a directory "c:/temp" all files in the directory will be included (and recursively if asked)
*
* Alternative directories are not pre-cached (instead of non Alternative files) and will used when a file is not found in the standard directories.
* For example, local data will be in the cached directories and server repository files will be in the Alternative files. If a new file is not
* found in the local data, we'll try to find it on the repository.
*
* When Alternative is false, all added file names must be unique or a warning will be display. In the Alternative directories, it could have
* more than one file with the same name.
*
* \warning the path you provide is case sensitive, you must be sure that the path name is exactly the same
*
* \param path the path name.k The separator for directories could be '/' or '\' (bit '\' will be translate into '/' in the function).
* \param recurse true if you want the function recurse in sub-directories.
* \param Alternative true if you want to add the path in the Alternative directories.
* \param progressCallBack is a progression callback interface pointer.
*/
static void addSearchPath (const std::string &path, bool recurse, bool alternative, class IProgressCallback *progressCallBack = NULL);
/** Used only for compatibility with the old CPath. In this case, we don't use the map to have the same behavior as the old CPath */
static void addSearchPath (const std::string &path) { addSearchPath (path, false, true, NULL); }
/** Same as AddSearchPath but with a file "c:/autoexec.bat" this file only will included. wildwards *doesn't* work */
static void addSearchFile (const std::string &file, bool remap = false, const std::string &virtual_ext = "", class NLMISC::IProgressCallback *progressCallBack = NULL);
/** Same as AddSearchPath but with a path file "c:/test.pth" all files name contain in this file will be included (the extention is used to know that it's a path file) */
static void addSearchListFile (const std::string &filename, bool recurse, bool alternative);
/** Same as AddSearchPath but with a big file "c:/test.nbf" all files name contained in the big file will be included (the extention (Nel Big File) is used to know that it's a big file) */
static void addSearchBigFile (const std::string &filename, bool recurse, bool alternative, class NLMISC::IProgressCallback *progressCallBack = NULL);
/** Same as AddSearchPath but with a xml pack file "c:/test.xml_pack" all files name contained in the xml pack will be included */
static void addSearchXmlpackFile (const std::string &sXmlpackFilename, bool recurse, bool alternative, class NLMISC::IProgressCallback *progressCallBack = NULL);
/** Remove all search path contains in the alternative directories */
static void removeAllAlternativeSearchPath ();
// Remove a set of big file from the search paths (and also from CBigFile)
static void removeBigFiles(const std::vector<std::string> &bnpFilenames);
/** Returns the long name (path + filename) for the specified file.
* The directory separator is always '/'.
* First, the lookup() lookups in standard directories (Alternative=false).
* If not found, it lookups in the Alternative directories.
* If not found the lookup() returns empty string "" (and generate an exception if throwException is true)
*
* The filename is not case sensitive so if the real filename is "FooBAR.Jpg" and you call lookup("fOOBar.jPg"), it'll
* return the real filename "FooBAR.Jpg"
*
* \param filename the file name you are seeking. (ex: "test.txt")
* \param throwException used for backward compatibility, set to true to generate an EPathNotFound.
* \param displayWarning set to false if you don't want the function displays a warning if the file is not found
* \param lookupInLocalDirectory if true, the lookup() will first try to open the file without path.
* \return empty string if file is not found or the full path + file name (ex: "c:/temp/test.txt");
*
* ***********************************************
* WARNING: This Method is NOT thread safe
* user must ensure that no mutator is called on CPath while async loading
* ***********************************************
*
*/
static std::string lookup (const std::string &filename, bool throwException = true, bool displayWarning = true, bool lookupInLocalDirectory = true);
/** Return if a file is present in the lookup map.
* The function changes filename into lower case and removes ended spaces before searching.
*
* \warning This function checks *only* in the map, not in local dir or alternative dir
*
* \param filename the file name you are seeking. (ex: "test.txt")
* \param lookupInLocalDirectory if true, the lookup() will first try to open the file without path.
* \return true if the filename exists in the map used by lookup to know where the file is, false otherwise
*/
static bool exists (const std::string &filename);
/** Clears the map that contains all cached files (Use this function to take into account new files).
*/
static void clearMap ();
/** Add a remapping function to allow file extension substitution.
* - eg remapExtension("dds", "tga", true) Where the boolean indicates whether
* the "dds" should replace a "tga" if one exists - again - a warning should
* be generated if the two are present.
*
* ie: If you have a file called pic.dds and you call remapExtension("dds", "tga", true),
* if you call lookup("pic.tga"), it'll return "pic.dds"
*
*/
static void remapExtension (const std::string &ext1, const std::string &ext2, bool substitute);
/** Add file remapping
* ie: If you have a file called pic.dds, and call remapFile("picture.dds", "pic.dds")
* calling lookup("picture.dds") will in fact call lookup("pic.dds")
*/
static void remapFile (const std::string &file1, const std::string &file2);
/** Load a file containing the remapped file (you must have done addsearchpath, this method use lookup)
* Format is remapped_name_file, real_file
* separators are , and \n
*/
static void loadRemappedFiles (const std::string &file);
static void display ();
/** Take a path and put it in the portable format and add a terminated / if needed
* ie: "C:\\Game/dir1" will become "C:/Game/dir1/" or "C:/Game/dir1" if addFinalSlash is false
*/
static std::string standardizePath (const std::string &path, bool addFinalSlash = true);
/** Replace / with \ for dos process. Use only this function if can't do another way.
* For example, if you do a system("copy data/toto data/tata"); it'll not work because dos doesn't
* understand /.
* But in the majority of case, / working (it works for fopen for example)
*/
static std::string standardizeDosPath (const std::string &path);
/** List all files in a directory.
* \param path path where files are scanned. No-op if empty
* \param recurse true if want to recurs directories
* \param wantDir true if want to add directories in result
* \param wantFile true if want to add files in result
* \param result list of string where directories/files names are added.
* \param progressCallBack is a progression callback interface pointer.
* \param showEverything false skips *.log files and CVS directories
*/
static void getPathContent (const std::string &path, bool recurse, bool wantDir, bool wantFile, std::vector<std::string> &result, class IProgressCallback *progressCallBack = NULL, bool showEverything=false);
/** Get the full path based on a file/path and the current directory. Example, imagine that the current path is c:\temp and toto is a directory
* getFullPath ("toto") returns "c:/temp/toto/"
* getFullPath ("../toto") returns "c:/temp/../toto/"
* getFullPath ("d:\dir\toto") returns "d:/dir/toto/"
* getFullPath ("\toto") returns "c:/toto/"
* getFullPath ("") returns "c:/temp/"
*
* \param path the path
* \return the full path
*/
static std::string getFullPath (const std::string &path, bool addFinalSlash = true);
/** Returns the current path of the application.
*/
static std::string getCurrentPath ();
/** Set the current path of the application.
*/
static bool setCurrentPath (const std::string &path);
/** Create a list of file having the requested extension.
*/
static void getFileList(const std::string &extension, std::vector<std::string> &filenames);
/** Create a list of file having the requested string in the filename and the requested extension.
*/
static void getFileListByName(const std::string &extension, const std::string &name, std::vector<std::string> &filenames);
/** Make a path relative to another if possible, else doesn't change it.
* \param basePath is the base path to be relative to.
* \param relativePath is the path to make relative to basePath.
* return true if relativePath as been done relative to basePath, false is relativePath has not been changed.
*/
static bool makePathRelative (const char *basePath, std::string &relativePath);
/** If File in this list is added more than one in an addSearchPath, it doesn't launch a warning.
*/
static void addIgnoredDoubleFile(const std::string &ignoredFile);
/** For the moment after memoryCompress you cant addsearchpath anymore
*/
static void memoryCompress();
static void memoryUncompress();
static bool isMemoryCompressed() { return getInstance()->_FileContainer.isMemoryCompressed(); }
/** Get the ms windows directory (in standardized way with end slash), or returns an empty string on other os
*/
static std::string getWindowsDirectory();
/** Get application directory.
* \return directory where applications should write files.
*/
static std::string getApplicationDirectory(const std::string &appName = "");
/** Get a temporary directory.
* \return temporary directory where applications should write files.
*/
static std::string getTemporaryDirectory();
// release singleton
static void releaseInstance();
private:
CPath()
{
}
/// The container used by the standard CPath
CFileContainer _FileContainer;
};
/**
* Utility class for file manipulation
* \author Vianney Lecroart
* \author Nevrax France
* \date 2001
*/
struct CFile
{
/**
* Retrieve the associated file name.
* An empty string is returned if the path is invalid
*/
static std::string getFilename (const std::string &filename);
/**
* Retrieve the associated file path with the trailing slash.
* Returns an empty string if the path is invalid
*/
static std::string getPath (const std::string &filename);
/**
* Just to know if it is a directory.
* _FileName empty and path not !!!
*/
static bool isDirectory (const std::string &filename);
/**
* Return true if the file exists.
* Warning: this test will also tell that the file does not
* exist if you don't have the rights to read it (Unix).
*/
static bool fileExists (const std::string &filename);
/**
* Return true if the file OR directory exists.
* Warning: this test will also tell that the file does not
* exist if you don't have the rights to read it (Unix).
*/
static bool isExists (const std::string& filename);
/**
* Create an empty file.
* Return true if the file has been correctly created.
*/
static bool createEmptyFile (const std::string& filename);
/**
* Return a new filename that doesn't exist. It's used for screenshot filename for example.
* example: findNewFile("foobar.tga");
* will try foobar001.tga, if the file exists, try foobar002.tga and so on until it finds an unexistant file.
*/
static std::string findNewFile (const std::string &filename);
/**
* Return the position between [begin,end[ of the last separator between path and filename ('/' or '\').
* If there's no separator, it returns string::npos.
*/
static int getLastSeparator (const std::string &filename);
static std::string getFilenameWithoutExtension (const std::string &filename);
static std::string getExtension (const std::string &filename);
/**
* Return the size of the file (in bytes).
*
* You have to provide the full path of the file (the function doesn't lookup)
*/
static uint32 getFileSize (const std::string &filename);
/**
* Return the size of the file (in bytes).
*/
static uint32 getFileSize (FILE *f);
/**
* Return Time of last modification of file. 0 if not found.
*
* You have to provide the full path of the file (the function doesn't lookup)
* The time is measured in second since 01-01-1970 0:0:0 UTC
*/
static uint32 getFileModificationDate(const std::string &filename);
/**
* Set the time of last modification of file.
*
* You have to provide the full path of the file (the function doesn't lookup)
* The time is measured in second since 01-01-1970 0:0:0 UTC
* Return 'true' if the file date has been changed or false in case of error.
*/
static bool setFileModificationDate(const std::string &filename, uint32 modTime);
/**
* Return creation Time of the file. 0 if not found.
*
* You have to provide the full path of the file (the function doesn't lookup)
*/
static uint32 getFileCreationDate(const std::string &filename);
/**
* Add a callback that will be call when the content file, named filename, changed.
* The system use the file modification date. To work, you need to call evenly the
* function checkFileChange(), this function only checks every 1s by default (you can
* change the default time)
*
* ie:
* void cb (const std::string &filename) { nlinfo ("the file %s changed", filename.c_str()); }
* CFile::addFileChangeCallback ("myfile.txt", cb);
*
*/
static void addFileChangeCallback (const std::string &filename, void (*)(const std::string &filename));
/**
* Remove a file that was previously added by addFileChangeCallback
*/
static void removeFileChangeCallback (const std::string &filename);
/**
* You have to call this function evenly (each frame for example) to enable the file change callback system.
* If the file not exists and is created in the run time, the callback will be called.
* If the file exists and is removed in the run time, the callback will be called.
*
* \param frequency the time in millisecond that we wait before check another time (1s by default).
*/
static void checkFileChange (TTime frequency = 1000);
/** Copy a file
* NB this keeps file attributes
* \param failIfExists If the destination file exists, nothing is done, and it returns false.
* \return true if the copy succeeded
*/
static bool copyFile(const std::string &dest, const std::string &src, bool failIfExists = false, class IProgressCallback *progress = NULL);
/** Compare 2 files
* \return true if both files exist and the files have same timestamp and size
*/
static bool quickFileCompare(const std::string &fileName0, const std::string &fileName1);
/** Compare 2 files
* \param maxBufSize fixes max memory space to use for the pair buffers used for data comparison (eg 16 would allow 8 bytes per buffer for the 2 buffers)
* \return true if both files exist and the files have same contents (timestamp is ignored)
*/
static bool thoroughFileCompare(const std::string &fileName0, const std::string &fileName1,uint32 maxBufSize=1024*1024*2);
/** Move a file
* NB this keeps file attributes
*/
static bool moveFile(const char *dest, const char *src);
/** Create a directory
* \return true if success
*/
static bool createDirectory(const std::string &dirname);
/** Create a directory and any missing parent directories
* \return true if success
*/
static bool createDirectoryTree(const std::string &dirname);
/** Try to set the file access to read/write if not already set.
* return true if the file doesn't exist or if the file already have RW access.
* Work actually only on Windows and returns always true on other platforms.
* \return true if RW access is granted
*/
static bool setRWAccess(const std::string &filename);
/** Delete a file if possible (change the write access if possible)
* \return true if the delete occurs.
*/
static bool deleteFile(const std::string &filename);
/** Delete a directory if possible (change the write access if possible)
* \return true if the delete occurs.
*/
static bool deleteDirectory(const std::string &filename);
/** Get temporary output filename.
* Call this method to get a temporary output filename. If you have successfully saved your data, delete the old filename and move the new one.
*/
static void getTemporaryOutputFilename (const std::string &originalFilename, std::string &tempFilename);
};
} // NLMISC
#endif // NL_PATH_H
/* End of path.h */