From 0ee1f060f9a25fe36fd12649f6797e3a6e4360b5 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Mon, 20 Feb 2012 22:18:02 +0000 Subject: [PATCH] Tweak path splitting. - Match dirname/basename semantics. - Accept both / and \ on Windows (as MinGW and several other apps do). --- common/os_string.hpp | 72 +++++++++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 18 deletions(-) diff --git a/common/os_string.hpp b/common/os_string.hpp index c92e6a8..c3fcf83 100644 --- a/common/os_string.hpp +++ b/common/os_string.hpp @@ -110,6 +110,39 @@ protected: return &buffer[0]; } + inline bool + isSep(char c) { + if (c == '/') { + return true; + } +#ifdef _WIN32 + if (c == '\\') { + return true; + } +#endif + return false; + } + + Buffer::iterator rfindSep(void) { + Buffer::iterator it = buffer.end(); + + // Skip trailing separators + while (it != buffer.begin() && isSep(*it)) { + --it; + } + + // Advance to the last separator + while (it != buffer.begin()) { + if (isSep(*it)) { + return it; + } + --it; + } + + return buffer.end(); + } + + public: /* @@ -280,14 +313,16 @@ public: /* - * String manipulation + * Path manipulation */ bool exists(void) const; + /* Trim directory (leaving base filename). + */ void trimDirectory(void) { - iterator sep = rfind(OS_DIR_SEP); + iterator sep = rfindSep(); if (sep != buffer.end()) { buffer.erase(buffer.begin(), sep + 1); } @@ -295,27 +330,28 @@ public: /* Trim filename component (leaving containing directory). * - * This function removes everything after the final path - * separator, as well as that separator itself if it is not the - * only remaining separator. - * - * Some specific consequences of the above: - * - * 1. A path with no separator at all is unchanged. - * 2. A path with a trailing separator has only that separator removed - * 3. A path of just the root directory is unchaged. + * - trailing separators are ignored + * - a path with no separator at all yields "." + * - a path consisting of just the root directory is left unchanged */ void trimFilename(void) { - iterator first = find(OS_DIR_SEP); - iterator last = rfind(OS_DIR_SEP); - if (last == buffer.end()) { + iterator sep = rfindSep(); + + // No separator found, so return '.' + if (sep == buffer.end()) { + buffer.resize(2); + buffer[0] = '.'; + buffer[1] = 0; return; } - if (last == first) { - buffer.erase(first + 1, end()); - } else { - buffer.erase(last, end()); + + // Root. Nothing to do. + if (sep == buffer.begin()) { + return; } + + // Trim filename + buffer.erase(sep, end()); } void trimExtension(void) { -- 2.43.0