Commit b913e6d6 authored by Andy Cedilnik's avatar Andy Cedilnik
Browse files

ENH: Move relative path to kwsys

parent f5164880
......@@ -1130,6 +1130,29 @@ kwsys_stl::string SystemTools::CropString(const kwsys_stl::string& s,
return n;
}
//----------------------------------------------------------------------------
std::vector<kwsys::String> SystemTools::SplitString(const char* p, char sep, bool isPath)
{
std::string path = p;
std::vector<kwsys::String> paths;
if(isPath && path[0] == '/')
{
path.erase(path.begin());
paths.push_back("/");
}
std::string::size_type pos1 = 0;
std::string::size_type pos2 = path.find(sep, pos1+1);
while(pos2 != std::string::npos)
{
paths.push_back(path.substr(pos1, pos2-pos1));
pos1 = pos2+1;
pos2 = path.find(sep, pos1+1);
}
paths.push_back(path.substr(pos1, pos2-pos1));
return paths;
}
//----------------------------------------------------------------------------
int SystemTools::EstimateFormatLength(const char *format, va_list ap)
{
......@@ -2395,6 +2418,85 @@ kwsys_stl::string SystemTools::CollapseFullPath(const char* in_path,
return newPath;
}
// compute the relative path from here to there
std::string SystemTools::RelativePath(const char* local, const char* remote)
{
if(!SystemTools::FileIsFullPath(local))
{
return "";
}
if(!SystemTools::FileIsFullPath(remote))
{
return "";
}
// split up both paths into arrays of strings using / as a separator
std::vector<kwsys::String> localSplit = SystemTools::SplitString(local, '/', true);
std::vector<kwsys::String> remoteSplit = SystemTools::SplitString(remote, '/', true);
std::vector<kwsys::String> commonPath; // store shared parts of path in this array
std::vector<kwsys::String> finalPath; // store the final relative path here
// count up how many matching directory names there are from the start
unsigned int sameCount = 0;
while(
((sameCount <= (localSplit.size()-1)) && (sameCount <= (remoteSplit.size()-1)))
&&
// for windows and apple do a case insensitive string compare
#if defined(_WIN32) || defined(__APPLE__)
cmSystemTools::Strucmp(localSplit[sameCount].c_str(),
remoteSplit[sameCount].c_str()) == 0
#else
localSplit[sameCount] == remoteSplit[sameCount]
#endif
)
{
// put the common parts of the path into the commonPath array
commonPath.push_back(localSplit[sameCount]);
// erase the common parts of the path from the original path arrays
localSplit[sameCount] = "";
remoteSplit[sameCount] = "";
sameCount++;
}
// If there is nothing in common but the root directory, then just
// return the full path.
if(sameCount <= 1)
{
return remote;
}
// for each entry that is not common in the local path
// add a ../ to the finalpath array, this gets us out of the local
// path into the remote dir
for(unsigned int i = 0; i < localSplit.size(); ++i)
{
if(localSplit[i].size())
{
finalPath.push_back("../");
}
}
// for each entry that is not common in the remote path add it
// to the final path.
for(std::vector<kwsys_stl::string>::iterator i = remoteSplit.begin();
i != remoteSplit.end(); ++i)
{
if(i->size())
{
finalPath.push_back(*i);
}
}
std::string relativePath; // result string
// now turn the array of directories into a unix path by puttint /
// between each entry that does not already have one
for(std::vector<kwsys_stl::string>::iterator i = finalPath.begin();
i != finalPath.end(); ++i)
{
if(relativePath.size() && relativePath[relativePath.size()-1] != '/')
{
relativePath += "/";
}
relativePath += *i;
}
return relativePath;
}
// OK, some fun stuff to get the actual case of a given path.
// Basically, you just need to call ShortPath, then GetLongPathName,
......
......@@ -20,6 +20,7 @@
#include <@KWSYS_NAMESPACE@/stl/map>
#include <@KWSYS_NAMESPACE@/Configure.h>
#include <@KWSYS_NAMESPACE@/String.hxx>
#include <sys/types.h>
......@@ -176,6 +177,13 @@ public:
*/
static kwsys_stl::string CropString(const kwsys_stl::string&,size_t max_len);
/** split a path by separator into an array of strings, default is /.
If isPath is true then the string is treated like a path and if
s starts with a / then the first element of the returned array will
be /, so /foo/bar will be [/, foo, bar]
*/
static std::vector<String> SplitString(const char* s, char separator = '/',
bool isPath = false);
/**
* Perform a case-independent string comparison
*/
......@@ -574,6 +582,16 @@ public:
static kwsys_stl::string FileExistsInParentDirectories(const char* fname,
const char* directory, const char* toplevel);
/** compute the relative path from local to remote. local must
be a directory. remote can be a file or a directory.
Both remote and local must be full paths. Basically, if
you are in directory local and you want to access the file in remote
what is the relative path to do that. For example:
/a/b/c/d to /a/b/c1/d1 -> ../../c1/d1
from /usr/src to /usr/src/test/blah/foo.cpp -> test/blah/foo.cpp
*/
static std::string RelativePath(const char* local, const char* remote);
/**
* Return file's modified time
*/
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment