Moved matchString from util.* to str.*; added new String::matchString method; fixed matchString doxygen comment (it confused pattern & string); added unit tests for matchString

svn-id: r34364
This commit is contained in:
Max Horn 2008-09-05 20:07:34 +00:00
parent 5388ecf722
commit 9bf7aa308e
5 changed files with 115 additions and 55 deletions

View file

@ -311,6 +311,14 @@ bool String::contains(char x) const {
return strchr(c_str(), x) != NULL;
}
bool String::matchString(const char *pat) const {
return Common::matchString(c_str(), pat);
}
bool String::matchString(const String &pat) const {
return Common::matchString(c_str(), pat.c_str());
}
void String::deleteLastChar() {
deleteChar(_size - 1);
}
@ -587,4 +595,40 @@ Common::String normalizePath(const Common::String &path, const char sep) {
return result;
}
bool matchString(const char *str, const char *pat) {
assert(str);
assert(pat);
const char *p = 0;
const char *q = 0;
for (;;) {
switch (*pat) {
case '*':
p = ++pat;
q = str;
break;
default:
if (*pat != *str) {
if (p) {
pat = p;
str = ++q;
if (!*str)
return !*pat;
break;
}
else
return false;
}
// fallthrough
case '?':
if (!*str)
return !*pat;
pat++;
str++;
}
}
}
} // End of namespace Common

View file

@ -149,6 +149,30 @@ public:
bool contains(const char *x) const;
bool contains(char x) const;
/**
* Simple DOS-style pattern matching function (understands * and ? like used in DOS).
* Taken from exult/files/listfiles.cc
*
* Token meaning:
* "*": any character, any amount of times.
* "?": any character, only once.
*
* Example strings/patterns:
* String: monkey.s01 Pattern: monkey.s?? => true
* String: monkey.s101 Pattern: monkey.s?? => false
* String: monkey.s99 Pattern: monkey.s?1 => false
* String: monkey.s101 Pattern: monkey.s* => true
* String: monkey.s99 Pattern: monkey.s*1 => false
*
* @param str Text to be matched against the given pattern.
* @param pat Glob pattern.
*
* @return true if str matches the pattern, false otherwise.
*/
bool matchString(const char *pat) const;
bool matchString(const String &pat) const;
inline const char *c_str() const { return _str; }
inline uint size() const { return _size; }
@ -172,11 +196,19 @@ public:
/** Set character c at position p. */
void insertChar(char c, uint32 p);
/** Clears the string, making it empty. */
void clear();
/** Convert all characters in the string to lowercase. */
void toLowercase();
/** Convert all characters in the string to uppercase. */
void toUppercase();
/**
* Removes trailing and leading whitespaces. Uses isspace() to decide
* what is whitespace and what not.
*/
void trim();
uint hash() const;
@ -257,6 +289,27 @@ Common::String lastPathComponent(const Common::String &path, const char sep);
Common::String normalizePath(const Common::String &path, const char sep);
/**
* Simple DOS-style pattern matching function (understands * and ? like used in DOS).
* Taken from exult/files/listfiles.cc
*
* Token meaning:
* "*": any character, any amount of times.
* "?": any character, only once.
*
* Example strings/patterns:
* String: monkey.s01 Pattern: monkey.s?? => true
* String: monkey.s101 Pattern: monkey.s?? => false
* String: monkey.s99 Pattern: monkey.s?1 => false
* String: monkey.s101 Pattern: monkey.s* => true
* String: monkey.s99 Pattern: monkey.s*1 => false
*
* @param str Text to be matched against the given pattern.
* @param pat Glob pattern.
*
* @return true if str matches the pattern, false otherwise.
*/
bool matchString(const char *str, const char *pat);
class StringList : public Array<String> {

View file

@ -63,39 +63,6 @@ extern bool isSmartphone(void);
namespace Common {
bool matchString(const char *str, const char *pat) {
const char *p = 0;
const char *q = 0;
for (;;) {
switch (*pat) {
case '*':
p = ++pat;
q = str;
break;
default:
if (*pat != *str) {
if (p) {
pat = p;
str = ++q;
if (!*str)
return !*pat;
break;
}
else
return false;
}
// fallthrough
case '?':
if (!*str)
return !*pat;
pat++;
str++;
}
}
}
StringTokenizer::StringTokenizer(const String &str, const String &delimiters) : _str(str), _delimiters(delimiters) {
reset();
}

View file

@ -52,28 +52,6 @@ template<typename T> inline void SWAP(T &a, T &b) { T tmp = a; a = b; b = tmp; }
namespace Common {
/**
* Simple DOS-style pattern matching function (understands * and ? like used in DOS).
* Taken from exult/files/listfiles.cc
*
* Token meaning:
* "*": any character, any amount of times.
* "?": any character, only once.
*
* Example strings/patterns:
* String: monkey.s?? Pattern: monkey.s01 => true
* String: monkey.s?? Pattern: monkey.s101 => false
* String: monkey.s?1 Pattern: monkey.s99 => false
* String: monkey.s* Pattern: monkey.s101 => true
* String: monkey.s*1 Pattern: monkey.s99 => false
*
* @param str Text to be matched against the given pattern.
* @param pat Glob pattern.
*
* @return true if str matches the pattern, false otherwise.
*/
bool matchString(const char *str, const char *pat);
/**
* A simple non-optimized string tokenizer.
*

View file

@ -189,4 +189,22 @@ class StringTestSuite : public CxxTest::TestSuite
TS_ASSERT(Common::normalizePath("foo//./bar//", '/') == "foo/bar");
TS_ASSERT(Common::normalizePath("foo//.bar//", '/') == "foo/.bar");
}
void test_matchString(void) {
TS_ASSERT( Common::matchString("monkey.s01", "monkey.s??"));
TS_ASSERT( Common::matchString("monkey.s99", "monkey.s??"));
TS_ASSERT(!Common::matchString("monkey.s101", "monkey.s??"));
TS_ASSERT( Common::matchString("monkey.s01", "monkey.s?1"));
TS_ASSERT(!Common::matchString("monkey.s99", "monkey.s?1"));
TS_ASSERT(!Common::matchString("monkey.s101", "monkey.s?1"));
TS_ASSERT( Common::matchString("monkey.s01", "monkey.s*"));
TS_ASSERT( Common::matchString("monkey.s99", "monkey.s*"));
TS_ASSERT( Common::matchString("monkey.s101", "monkey.s*"));
TS_ASSERT( Common::matchString("monkey.s01", "monkey.s*1"));
TS_ASSERT(!Common::matchString("monkey.s99", "monkey.s*1"));
TS_ASSERT( Common::matchString("monkey.s101", "monkey.s*1"));
}
};