Changed: Add a parameter to CPath::makePathAbsolute to simplify the path (remove all . and ..)

This commit is contained in:
kervala 2016-01-23 09:44:41 +01:00
parent 7f054799b4
commit 94b033caf9
2 changed files with 92 additions and 34 deletions

View file

@ -510,9 +510,10 @@ public:
/** Make path absolute /** Make path absolute
* \param relativePath - The relative path * \param relativePath - The relative path
* \param directory - the directory to which the path is relative to * \param directory - the directory to which the path is relative to
* \param simplify - if we should simplify or not the path (convert . and .. in path)
* returns the absolute path, or empty if something went wrong. * returns the absolute path, or empty if something went wrong.
*/ */
static std::string makePathAbsolute (const std::string &relativePath, const std::string &directory ); static std::string makePathAbsolute (const std::string &relativePath, const std::string &directory, bool simplify = false );
/** Return if a path is absolute or not. /** Return if a path is absolute or not.
* \param path - The path * \param path - The path

View file

@ -2546,55 +2546,112 @@ bool CPath::makePathRelative (const char *basePath, std::string &relativePath)
return false; return false;
} }
std::string CPath::makePathAbsolute( const std::string &relativePath, const std::string &directory ) std::string CPath::makePathAbsolute( const std::string &relativePath, const std::string &directory, bool simplify )
{ {
if( relativePath.empty() ) if( relativePath.empty() )
return ""; return "";
if( directory.empty() ) if( directory.empty() )
return ""; return "";
std::string absolutePath;
#ifdef NL_OS_WINDOWS #ifdef NL_OS_WINDOWS
// Windows network address. Eg.: \\someshare\path // Windows network address. Eg.: \\someshare\path
if( ( relativePath[ 0 ] == '\\' ) && ( relativePath[ 1 ] == '\\' ) ) if ((relativePath[0] == '\\') && (relativePath[1] == '\\'))
return relativePath; {
absolutePath = relativePath;
}
// Normal Windows absolute path. Eg.: C:\something // Normal Windows absolute path. Eg.: C:\something
// //
if( isalpha( relativePath[ 0 ] ) && ( relativePath[ 1 ] == ':' ) && ( ( relativePath[ 2 ] == '\\' ) || ( relativePath[ 2 ] == '/' ) ) ) else if (isalpha(relativePath[0]) && (relativePath[1] == ':') && ((relativePath[2] == '\\') || (relativePath[2] == '/')))
return relativePath; {
absolutePath = relativePath;
}
#else #else
// Unix filesystem absolute path // Unix filesystem absolute path
if( relativePath[ 0 ] == '/' ) if (relativePath[0] == '/')
return relativePath; {
absolutePath = relativePath;
}
#endif #endif
// Add a slash to the directory if necessary.
// If the relative path starts with dots we need a slash.
// If the relative path starts with a slash we don't.
// If it starts with neither, we need a slash.
bool needSlash = true;
char c = relativePath[ 0 ];
if( ( c == '\\' ) || ( c == '/' ) )
needSlash = false;
bool hasSlash = false;
std::string npath = directory;
c = npath[ npath.size() - 1 ];
if( ( c == '\\' ) || ( c == '/' ) )
hasSlash = true;
if( needSlash && !hasSlash )
npath += '/';
else else
if( hasSlash && !needSlash ) {
npath.resize( npath.size() - 1 ); // Add a slash to the directory if necessary.
// If the relative path starts with dots we need a slash.
// If the relative path starts with a slash we don't.
// If it starts with neither, we need a slash.
bool needSlash = true;
char c = relativePath[0];
if ((c == '\\') || (c == '/'))
needSlash = false;
// Now build the new absolute path bool hasSlash = false;
npath += relativePath; absolutePath = directory;
npath = standardizePath( npath, false ); c = absolutePath[absolutePath.size() - 1];
if ((c == '\\') || (c == '/'))
hasSlash = true;
return npath; if (needSlash && !hasSlash)
absolutePath += '/';
else
if (hasSlash && !needSlash)
absolutePath.resize(absolutePath.size() - 1);
// Now build the new absolute path
absolutePath += relativePath;
absolutePath = standardizePath(absolutePath, true);
}
if (simplify)
{
// split all components path to manage parent directories
std::vector<std::string> tokens;
explode(absolutePath, std::string("/"), tokens, true);
std::vector<std::string> directoryParts;
// process all components
for(uint i = 0, len = tokens.size(); i < len; ++i)
{
std::string token = tokens[i];
// current directory
if (token != ".")
{
// parent directory
if (token == "..")
{
// remove last directory
directoryParts.pop_back();
}
else
{
// append directory
directoryParts.push_back(token);
}
}
}
if (!directoryParts.empty())
{
absolutePath = directoryParts[0];
// rebuild the whole absolute path
for(uint i = 1, len = directoryParts.size(); i < len; ++i)
absolutePath += "/" + directoryParts[i];
// add trailing slash
absolutePath += "/";
}
else
{
// invalid path
absolutePath.clear();
}
}
return absolutePath;
} }
bool CPath::isAbsolutePath(const std::string &path) bool CPath::isAbsolutePath(const std::string &path)