From e5a8e115bc26e6a7f6b25dc2450e9bb28fca6fa1 Mon Sep 17 00:00:00 2001 From: Andy Cedilnik Date: Tue, 7 Feb 2006 10:23:17 -0500 Subject: ENH: Move relative path to kwsys --- Source/cmSystemTools.cxx | 92 +----------------------------------- Source/cmSystemTools.h | 9 +--- Source/kwsys/SystemTools.cxx | 102 ++++++++++++++++++++++++++++++++++++++++ Source/kwsys/SystemTools.hxx.in | 18 +++++++ 4 files changed, 123 insertions(+), 98 deletions(-) diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 425d2f5..52032f0 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -1225,29 +1225,6 @@ bool cmSystemTools::CreateSymlink(const char* origName, const char* newName) #endif -std::vector cmSystemTools::SplitString(const char* p, char sep, bool isPath) -{ - std::string path = p; - std::vector 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 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); } - - // split up both paths into arrays of strings using / as a separator - std::vector localSplit = cmSystemTools::SplitString(local, '/', true); - std::vector remoteSplit = cmSystemTools::SplitString(remote, '/', true); - std::vector commonPath; // store shared parts of path in this array - std::vector 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::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::iterator i = finalPath.begin(); - i != finalPath.end(); ++i) - { - if(relativePath.size() && relativePath[relativePath.size()-1] != '/') - { - relativePath += "/"; - } - relativePath += *i; - } - return relativePath; + return cmsys::SystemTools::RelativePath(local, remote); } + class cmDeletingCharVector : public std::vector { public: diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 2895fff..6c5be99 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -285,14 +285,7 @@ public: from /usr/src to /usr/src/test/blah/foo.cpp -> test/blah/foo.cpp */ 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 SplitString(const char* s, char separator = '/', - bool isPath = false); + /** put a string into the environment of the form var=value */ static bool PutEnv(const char* value); diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index ee59852..5da7606 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -1131,6 +1131,29 @@ kwsys_stl::string SystemTools::CropString(const kwsys_stl::string& s, } //---------------------------------------------------------------------------- +std::vector SystemTools::SplitString(const char* p, char sep, bool isPath) +{ + std::string path = p; + std::vector 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) { if (!format) @@ -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 localSplit = SystemTools::SplitString(local, '/', true); + std::vector remoteSplit = SystemTools::SplitString(remote, '/', true); + std::vector commonPath; // store shared parts of path in this array + std::vector 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::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::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, diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in index 703f739..31bfa9a 100644 --- a/Source/kwsys/SystemTools.hxx.in +++ b/Source/kwsys/SystemTools.hxx.in @@ -20,6 +20,7 @@ #include <@KWSYS_NAMESPACE@/stl/map> #include <@KWSYS_NAMESPACE@/Configure.h> +#include <@KWSYS_NAMESPACE@/String.hxx> #include @@ -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 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 */ -- cgit v0.12