Created
May 31, 2013 12:53
-
-
Save kahrl/5684778 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/filesys.cpp b/src/filesys.cpp | |
index 06b0e48..21f9f88 100644 | |
--- a/src/filesys.cpp | |
+++ b/src/filesys.cpp | |
@@ -146,6 +146,11 @@ bool IsDir(std::string path) | |
(attr & FILE_ATTRIBUTE_DIRECTORY)); | |
} | |
+bool IsDirDelimiter(char c) | |
+{ | |
+ return c == '/' || c == '\\'; | |
+} | |
+ | |
bool RecursiveDelete(std::string path) | |
{ | |
infostream<<"Recursively deleting \""<<path<<"\""<<std::endl; | |
@@ -335,6 +340,11 @@ bool IsDir(std::string path) | |
return ((statbuf.st_mode & S_IFDIR) == S_IFDIR); | |
} | |
+bool IsDirDelimiter(char c) | |
+{ | |
+ return c == '/'; | |
+} | |
+ | |
bool RecursiveDelete(std::string path) | |
{ | |
/* | |
@@ -448,16 +458,14 @@ bool RecursiveDeleteContent(std::string path) | |
bool CreateAllDirs(std::string path) | |
{ | |
- size_t pos; | |
std::vector<std::string> tocreate; | |
std::string basepath = path; | |
while(!PathExists(basepath)) | |
{ | |
tocreate.push_back(basepath); | |
- pos = basepath.rfind(DIR_DELIM_C); | |
- if(pos == std::string::npos) | |
+ basepath = RemoveLastPathComponent(basepath); | |
+ if(basepath.empty()) | |
break; | |
- basepath = basepath.substr(0,pos); | |
} | |
for(int i=tocreate.size()-1;i>=0;i--) | |
if(!CreateDir(tocreate[i])) | |
@@ -527,5 +535,83 @@ bool CopyDir(std::string source,std::string target) | |
} | |
} | |
+std::string RemoveLastPathComponent(std::string path, | |
+ std::string *removed, int count) | |
+{ | |
+ if (removed) | |
+ *removed = ""; | |
+ | |
+ size_t remaining = path.size(); | |
+ | |
+ for (int i = 0; i < count; ++i){ | |
+ // strip a dir delimiter | |
+ while(remaining != 0 && IsDirDelimiter(path[remaining-1])) | |
+ remaining--; | |
+ // strip a path component | |
+ size_t component_end = remaining; | |
+ while(remaining != 0 && !IsDirDelimiter(path[remaining-1])) | |
+ remaining--; | |
+ size_t component_start = remaining; | |
+ // strip a dir delimiter | |
+ while(remaining != 0 && IsDirDelimiter(path[remaining-1])) | |
+ remaining--; | |
+ if(removed){ | |
+ std::string component = path.substr(component_start, | |
+ component_end - component_start); | |
+ if(i) | |
+ *removed = component + DIR_DELIM + *removed; | |
+ else | |
+ *removed = component; | |
+ } | |
+ } | |
+ return path.substr(0, remaining); | |
+} | |
+ | |
+std::string RemoveRelativePathComponents(std::string path) | |
+{ | |
+ size_t pos = path.size(); | |
+ size_t dotdot_count = 0; | |
+ while(pos != 0){ | |
+ size_t component_with_delim_end = pos; | |
+ // skip a dir delimiter | |
+ while(pos != 0 && IsDirDelimiter(path[pos-1])) | |
+ pos--; | |
+ // strip a path component | |
+ size_t component_end = pos; | |
+ while(pos != 0 && !IsDirDelimiter(path[pos-1])) | |
+ pos--; | |
+ size_t component_start = pos; | |
+ | |
+ std::string component = path.substr(component_start, component_end - component_start); | |
+ bool remove_this_component = false; | |
+ if(component == "."){ | |
+ remove_this_component = true; | |
+ } | |
+ else if(component == ".."){ | |
+ remove_this_component = true; | |
+ dotdot_count += 1; | |
+ } | |
+ else if(dotdot_count != 0){ | |
+ remove_this_component = true; | |
+ dotdot_count -= 1; | |
+ } | |
+ | |
+ if(remove_this_component){ | |
+ while(pos != 0 && IsDirDelimiter(path[pos-1])) | |
+ pos--; | |
+ path = path.substr(0, pos) + DIR_DELIM + | |
+ path.substr(component_with_delim_end, std::string::npos); | |
+ std::cerr<<"[component removed] "<<path<<std::endl; | |
+ pos++; | |
+ } | |
+ } | |
+ | |
+ if(dotdot_count > 0) | |
+ return ""; | |
+ else | |
+ return path; | |
+} | |
+ | |
+ | |
} // namespace fs | |
diff --git a/src/filesys.h b/src/filesys.h | |
index 15fa0ad..560d8d6 100644 | |
--- a/src/filesys.h | |
+++ b/src/filesys.h | |
@@ -26,10 +26,8 @@ | |
#ifdef _WIN32 // WINDOWS | |
#define DIR_DELIM "\\" | |
-#define DIR_DELIM_C '\\' | |
#else // POSIX | |
#define DIR_DELIM "/" | |
-#define DIR_DELIM_C '/' | |
#endif | |
namespace fs | |
@@ -49,6 +47,8 @@ struct DirListNode | |
bool IsDir(std::string path); | |
+bool IsDirDelimiter(char c); | |
+ | |
// Only pass full paths to this one. True on success. | |
// NOTE: The WIN32 version returns always true. | |
bool RecursiveDelete(std::string path); | |
@@ -72,6 +72,18 @@ struct DirListNode | |
// Copy directory and all subdirectorys | |
bool CopyDir(std::string source,std::string target); | |
+// Remove last path component and the dir delimiter before and/or after it, | |
+// returns "" if there is only one path component. | |
+// removed: If non-NULL, receives the removed component(s). | |
+// count: Number of components to remove | |
+std::string RemoveLastPathComponent(std::string path, | |
+ std::string *removed = NULL, int count = 1); | |
+ | |
+// Remove "." and ".." path components and for every ".." removed, remove | |
+// the last normal path component before it. Unlike AbsolutePath, | |
+// this does not resolve symlinks and check for existence of directories. | |
+std::string RemoveRelativePathComponents(std::string path); | |
+ | |
//get absolute path from a given relative one | |
std::string AbsolutePath(std::string path); | |
diff --git a/src/map.cpp b/src/map.cpp | |
index d5ab8eb..434170a 100644 | |
--- a/src/map.cpp | |
+++ b/src/map.cpp | |
@@ -3228,17 +3228,18 @@ v2s16 ServerMap::getSectorPos(std::string dirname) | |
{ | |
unsigned int x, y; | |
int r; | |
- size_t spos = dirname.rfind(DIR_DELIM_C) + 1; | |
- assert(spos != std::string::npos); | |
- if(dirname.size() - spos == 8) | |
+ std::string component; | |
+ fs::RemoveLastPathComponent(dirname, &component, 1); | |
+ if(component.size() == 8) | |
{ | |
// Old layout | |
- r = sscanf(dirname.substr(spos).c_str(), "%4x%4x", &x, &y); | |
+ r = sscanf(component.c_str(), "%4x%4x", &x, &y); | |
} | |
- else if(dirname.size() - spos == 3) | |
+ else if(component.size() == 3) | |
{ | |
// New layout | |
- r = sscanf(dirname.substr(spos-4).c_str(), "%3x" DIR_DELIM "%3x", &x, &y); | |
+ fs::RemoveLastPathComponent(dirname, &component, 2); | |
+ r = sscanf(component.c_str(), "%3x" DIR_DELIM "%3x", &x, &y); | |
// Sign-extend the 12 bit values up to 16 bits... | |
if(x&0x800) x|=0xF000; | |
if(y&0x800) y|=0xF000; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment