Added two new global funcs which ease proper handling of 'path' strings: Common::lastPathComponent() and Common::normalizePath()
svn-id: r34272
This commit is contained in:
parent
9c5d81fb83
commit
155b8606c1
3 changed files with 131 additions and 0 deletions
|
@ -524,4 +524,71 @@ char *trim(char *t) {
|
||||||
return rtrim(ltrim(t));
|
return rtrim(ltrim(t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Common::String lastPathComponent(const Common::String &path, const char sep) {
|
||||||
|
const char *str = path.c_str();
|
||||||
|
const char *last = str + path.size();
|
||||||
|
|
||||||
|
// Skip over trailing slashes
|
||||||
|
while (last > str && *(last-1) == sep)
|
||||||
|
--last;
|
||||||
|
|
||||||
|
// Path consisted of only slashes -> return empty string
|
||||||
|
if (last == str)
|
||||||
|
return Common::String();
|
||||||
|
|
||||||
|
// Now scan the whole component
|
||||||
|
const char *first = last - 1;
|
||||||
|
while (first >= str && *first != sep)
|
||||||
|
--first;
|
||||||
|
|
||||||
|
if (*first == sep)
|
||||||
|
first++;
|
||||||
|
|
||||||
|
return Common::String(first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::String normalizePath(const Common::String &path, const char sep) {
|
||||||
|
if (path.empty())
|
||||||
|
return path;
|
||||||
|
|
||||||
|
const char *cur = path.c_str();
|
||||||
|
Common::String result;
|
||||||
|
|
||||||
|
// If there is a leading slash, preserve that:
|
||||||
|
if (*cur == sep) {
|
||||||
|
result += sep;
|
||||||
|
while (*cur == sep)
|
||||||
|
++cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan till the end of the String
|
||||||
|
while (*cur != 0) {
|
||||||
|
const char *start = cur;
|
||||||
|
|
||||||
|
// Scan till the next path separator resp. the end of the string
|
||||||
|
while (*cur != sep && *cur != 0)
|
||||||
|
cur++;
|
||||||
|
|
||||||
|
const Common::String component(start, cur);
|
||||||
|
|
||||||
|
// Skip empty components and dot components, add all others
|
||||||
|
if (!component.empty() && component != ".") {
|
||||||
|
// Add a separator before the component, unless the result
|
||||||
|
// string already ends with one (which happens only if the
|
||||||
|
// path *starts* with a separator).
|
||||||
|
if (!result.empty() && result.lastChar() != sep)
|
||||||
|
result += sep;
|
||||||
|
|
||||||
|
// Add the component
|
||||||
|
result += component;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip over separator chars
|
||||||
|
while (*cur == sep)
|
||||||
|
cur++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
} // End of namespace Common
|
} // End of namespace Common
|
||||||
|
|
32
common/str.h
32
common/str.h
|
@ -227,6 +227,38 @@ extern char *ltrim(char *t);
|
||||||
extern char *rtrim(char *t);
|
extern char *rtrim(char *t);
|
||||||
extern char *trim(char *t);
|
extern char *trim(char *t);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the last component of a given path.
|
||||||
|
*
|
||||||
|
* Examples:
|
||||||
|
* /foo/bar.txt would return 'bar.txt'
|
||||||
|
* /foo/bar/ would return 'bar'
|
||||||
|
* /foo/./bar// would return 'bar'
|
||||||
|
*
|
||||||
|
* @param path the path of which we want to know the last component
|
||||||
|
* @param sep character used to separate path components
|
||||||
|
* @return The last component of the path.
|
||||||
|
*/
|
||||||
|
Common::String lastPathComponent(const Common::String &path, const char sep);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize a gien path to a canonical form. In particular:
|
||||||
|
* - trailing separators are removed: /foo/bar/ -> /foo/bar
|
||||||
|
* - double separators (= empty components) are removed: /foo//bar -> /foo/bar
|
||||||
|
* - dot components are removed: /foo/./bar -> /foo/bar
|
||||||
|
*
|
||||||
|
* @todo remove double dot components: /foo/baz/../bar -> /foo/bar
|
||||||
|
*
|
||||||
|
* @param path the path to normalize
|
||||||
|
* @param sep the separator token (usually '/' on Unix-style systems, or '\\' on Windows based stuff)
|
||||||
|
* @return the normalized path
|
||||||
|
*/
|
||||||
|
Common::String normalizePath(const Common::String &path, const char sep);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class StringList : public Array<String> {
|
class StringList : public Array<String> {
|
||||||
public:
|
public:
|
||||||
void push_back(const char *str) {
|
void push_back(const char *str) {
|
||||||
|
|
|
@ -157,4 +157,36 @@ class StringTestSuite : public CxxTest::TestSuite
|
||||||
TS_ASSERT_EQUALS(str, "TEST IT, NOW! 42");
|
TS_ASSERT_EQUALS(str, "TEST IT, NOW! 42");
|
||||||
TS_ASSERT_EQUALS(str2, "Test it, NOW! 42");
|
TS_ASSERT_EQUALS(str2, "Test it, NOW! 42");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_lastPathComponent(void) {
|
||||||
|
TS_ASSERT(Common::lastPathComponent("/", '/') == "");
|
||||||
|
TS_ASSERT(Common::lastPathComponent("/foo/bar", '/') == "bar");
|
||||||
|
TS_ASSERT(Common::lastPathComponent("/foo//bar/", '/') == "bar");
|
||||||
|
TS_ASSERT(Common::lastPathComponent("/foo/./bar", '/') == "bar");
|
||||||
|
TS_ASSERT(Common::lastPathComponent("/foo//./bar//", '/') == "bar");
|
||||||
|
TS_ASSERT(Common::lastPathComponent("/foo//.bar//", '/') == ".bar");
|
||||||
|
|
||||||
|
TS_ASSERT(Common::lastPathComponent("", '/') == "");
|
||||||
|
TS_ASSERT(Common::lastPathComponent("foo/bar", '/') == "bar");
|
||||||
|
TS_ASSERT(Common::lastPathComponent("foo//bar/", '/') == "bar");
|
||||||
|
TS_ASSERT(Common::lastPathComponent("foo/./bar", '/') == "bar");
|
||||||
|
TS_ASSERT(Common::lastPathComponent("foo//./bar//", '/') == "bar");
|
||||||
|
TS_ASSERT(Common::lastPathComponent("foo//.bar//", '/') == ".bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_normalizePath(void) {
|
||||||
|
TS_ASSERT(Common::normalizePath("/", '/') == "/");
|
||||||
|
TS_ASSERT(Common::normalizePath("/foo/bar", '/') == "/foo/bar");
|
||||||
|
TS_ASSERT(Common::normalizePath("/foo//bar/", '/') == "/foo/bar");
|
||||||
|
TS_ASSERT(Common::normalizePath("/foo/./bar", '/') == "/foo/bar");
|
||||||
|
TS_ASSERT(Common::normalizePath("/foo//./bar//", '/') == "/foo/bar");
|
||||||
|
TS_ASSERT(Common::normalizePath("/foo//.bar//", '/') == "/foo/.bar");
|
||||||
|
|
||||||
|
TS_ASSERT(Common::normalizePath("", '/') == "");
|
||||||
|
TS_ASSERT(Common::normalizePath("foo/bar", '/') == "foo/bar");
|
||||||
|
TS_ASSERT(Common::normalizePath("foo//bar/", '/') == "foo/bar");
|
||||||
|
TS_ASSERT(Common::normalizePath("foo/./bar", '/') == "foo/bar");
|
||||||
|
TS_ASSERT(Common::normalizePath("foo//./bar//", '/') == "foo/bar");
|
||||||
|
TS_ASSERT(Common::normalizePath("foo//.bar//", '/') == "foo/.bar");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue