summaryrefslogtreecommitdiffstats
path: root/src/util.cc
diff options
context:
space:
mode:
authorThiago Farina <tfransosi@gmail.com>2011-03-19 21:53:43 (GMT)
committerEvan Martin <martine@danga.com>2011-04-15 19:20:51 (GMT)
commit89a75eff08cd7355f07235938aff4769f97068e5 (patch)
treefff51cd97b561d91ef6a670d21116cd0b03543e9 /src/util.cc
parent343c526e6a0c35816c4876bfc923cef15ef7a989 (diff)
downloadNinja-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.cc54
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;
+}