diff options
Diffstat (limited to 'Source/kwsys/SystemTools.cxx')
-rw-r--r-- | Source/kwsys/SystemTools.cxx | 102 |
1 files changed, 102 insertions, 0 deletions
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<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) { 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<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, |