ENH: Move relative path to kwsys

This commit is contained in:
Andy Cedilnik 2006-02-07 10:23:17 -05:00
parent f71a085f74
commit e5a8e115bc
4 changed files with 123 additions and 98 deletions

View File

@ -1225,29 +1225,6 @@ bool cmSystemTools::CreateSymlink(const char* origName, const char* newName)
#endif #endif
std::vector<cmStdString> cmSystemTools::SplitString(const char* p, char sep, bool isPath)
{
std::string path = p;
std::vector<cmStdString> 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;
}
// compute the relative path from here to there // compute the relative path from here to there
std::string cmSystemTools::RelativePath(const char* local, const char* remote) std::string cmSystemTools::RelativePath(const char* local, const char* remote)
{ {
@ -1259,74 +1236,9 @@ std::string cmSystemTools::RelativePath(const char* local, const char* remote)
{ {
cmSystemTools::Error("RelativePath must be passed a full path to remote: ", remote); cmSystemTools::Error("RelativePath must be passed a full path to remote: ", remote);
} }
return cmsys::SystemTools::RelativePath(local, remote);
// split up both paths into arrays of strings using / as a separator
std::vector<cmStdString> localSplit = cmSystemTools::SplitString(local, '/', true);
std::vector<cmStdString> remoteSplit = cmSystemTools::SplitString(remote, '/', true);
std::vector<cmStdString> commonPath; // store shared parts of path in this array
std::vector<cmStdString> 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<cmStdString>::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<cmStdString>::iterator i = finalPath.begin();
i != finalPath.end(); ++i)
{
if(relativePath.size() && relativePath[relativePath.size()-1] != '/')
{
relativePath += "/";
}
relativePath += *i;
}
return relativePath;
} }
class cmDeletingCharVector : public std::vector<char*> class cmDeletingCharVector : public std::vector<char*>
{ {
public: public:

View File

@ -285,14 +285,7 @@ public:
from /usr/src to /usr/src/test/blah/foo.cpp -> test/blah/foo.cpp from /usr/src to /usr/src/test/blah/foo.cpp -> test/blah/foo.cpp
*/ */
static std::string RelativePath(const char* local, const char* remote); static std::string RelativePath(const char* local, const char* remote);
/** 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<cmStdString> SplitString(const char* s, char separator = '/',
bool isPath = false);
/** put a string into the environment /** put a string into the environment
of the form var=value */ of the form var=value */
static bool PutEnv(const char* value); static bool PutEnv(const char* value);

View File

@ -1130,6 +1130,29 @@ kwsys_stl::string SystemTools::CropString(const kwsys_stl::string& s,
return n; 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) int SystemTools::EstimateFormatLength(const char *format, va_list ap)
{ {
@ -2395,6 +2418,85 @@ kwsys_stl::string SystemTools::CollapseFullPath(const char* in_path,
return newPath; 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. // OK, some fun stuff to get the actual case of a given path.
// Basically, you just need to call ShortPath, then GetLongPathName, // Basically, you just need to call ShortPath, then GetLongPathName,

View File

@ -20,6 +20,7 @@
#include <@KWSYS_NAMESPACE@/stl/map> #include <@KWSYS_NAMESPACE@/stl/map>
#include <@KWSYS_NAMESPACE@/Configure.h> #include <@KWSYS_NAMESPACE@/Configure.h>
#include <@KWSYS_NAMESPACE@/String.hxx>
#include <sys/types.h> #include <sys/types.h>
@ -176,6 +177,13 @@ public:
*/ */
static kwsys_stl::string CropString(const kwsys_stl::string&,size_t max_len); 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 * Perform a case-independent string comparison
*/ */
@ -574,6 +582,16 @@ public:
static kwsys_stl::string FileExistsInParentDirectories(const char* fname, static kwsys_stl::string FileExistsInParentDirectories(const char* fname,
const char* directory, const char* toplevel); 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 * Return file's modified time
*/ */