diff options
author | Thiago Farina <tfransosi@gmail.com> | 2011-03-19 21:53:43 (GMT) |
---|---|---|
committer | Evan Martin <martine@danga.com> | 2011-04-15 19:20:51 (GMT) |
commit | 89a75eff08cd7355f07235938aff4769f97068e5 (patch) | |
tree | fff51cd97b561d91ef6a670d21116cd0b03543e9 /src/util.cc | |
parent | 343c526e6a0c35816c4876bfc923cef15ef7a989 (diff) | |
download | Ninja-89a75eff08cd7355f07235938aff4769f97068e5.zip Ninja-89a75eff08cd7355f07235938aff4769f97068e5.tar.gz Ninja-89a75eff08cd7355f07235938aff4769f97068e5.tar.bz2 |
Move CanonicalizePath into util.h so it can be shared by the other modules.
Also add util_test.cc and move the CanonicalizePathTest into there.
Signed-off-by: Thiago Farina <tfarina@chromium.org>
Diffstat (limited to 'src/util.cc')
-rw-r--r-- | src/util.cc | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/src/util.cc b/src/util.cc index 1968702..d0236bc 100644 --- a/src/util.cc +++ b/src/util.cc @@ -18,6 +18,8 @@ #include <stdio.h> #include <stdlib.h> +#include <vector> + void Fatal(const char* msg, ...) { va_list ap; fprintf(stderr, "FATAL: "); @@ -27,3 +29,55 @@ void Fatal(const char* msg, ...) { fprintf(stderr, "\n"); exit(1); } + +bool CanonicalizePath(std::string* path, std::string* err) { + // Try to fast-path out the common case. + if (path->find("/.") == std::string::npos && + path->find("./") == std::string::npos) { + return true; + } + + std::string inpath = *path; + std::vector<const char*> parts; + for (std::string::size_type start = 0; start < inpath.size(); ++start) { + std::string::size_type end = inpath.find('/', start); + if (end == std::string::npos) + end = inpath.size(); + else + inpath[end] = 0; + parts.push_back(inpath.data() + start); + start = end; + } + + std::vector<const char*>::iterator i = parts.begin(); + while (i != parts.end()) { + const char* part = *i; + if (part[0] == '.') { + if (part[1] == 0) { + // "."; strip. + parts.erase(i); + continue; + } else if (part[1] == '.' && part[2] == 0) { + // ".."; go up one. + if (i == parts.begin()) { + *err = "can't canonicalize path '" + *path + "' that reaches " + "above its directory"; + return false; + } + --i; + parts.erase(i, i + 2); + continue; + } + } + ++i; + } + path->clear(); + + for (i = parts.begin(); i != parts.end(); ++i) { + if (!path->empty()) + path->push_back('/'); + path->append(*i); + } + + return true; +} |