summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authorakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-01 20:50:55 +0000
committerakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-01 20:50:55 +0000
commite11de7254efb71fbe5b26b113a8e2e5bdd8da15f (patch)
treebe8df3ca21aeb1c777d1efbfa6266174c0eb870d /base
parent86b531b3f6d8b5353a159456dba3bc03ebc68060 (diff)
downloadchromium_src-e11de7254efb71fbe5b26b113a8e2e5bdd8da15f.zip
chromium_src-e11de7254efb71fbe5b26b113a8e2e5bdd8da15f.tar.gz
chromium_src-e11de7254efb71fbe5b26b113a8e2e5bdd8da15f.tar.bz2
Wrote a custom pattern matcher for vmodule.
The custom pattern matcher matches any slash (forward or backward) to any slash. It also does not do escaping like MatchPattern(). Finally, '?' matches exactly one character, which matches google-glog behavior (MatchPattern() matches '?' to 0 or 1 character). BUG=61123 TEST=New unittests Review URL: http://codereview.chromium.org/4205005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@64661 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r--base/logging.h4
-rw-r--r--base/vlog.cc66
-rw-r--r--base/vlog.h13
-rw-r--r--base/vlog_unittest.cc55
4 files changed, 123 insertions, 15 deletions
diff --git a/base/logging.h b/base/logging.h
index 4b3caca..68a1c74 100644
--- a/base/logging.h
+++ b/base/logging.h
@@ -87,9 +87,9 @@
// b. VLOG(1) and lower messages to be printed from icon_loader.{h,cc}
// c. VLOG(3) and lower messages to be printed from files prefixed with
// "browser"
-// c. VLOG(4) and lower messages to be printed from files under a
+// d. VLOG(4) and lower messages to be printed from files under a
// "chromeos" directory.
-// d. VLOG(0) and lower messages to be printed from elsewhere
+// e. VLOG(0) and lower messages to be printed from elsewhere
//
// The wildcarding functionality shown by (c) supports both '*' (match
// 0 or more characters) and '?' (match any single character)
diff --git a/base/vlog.cc b/base/vlog.cc
index 3e892d3..8c615cb 100644
--- a/base/vlog.cc
+++ b/base/vlog.cc
@@ -5,9 +5,9 @@
#include "base/vlog.h"
#include "base/basictypes.h"
+#include "base/logging.h"
#include "base/string_number_conversions.h"
#include "base/string_split.h"
-#include "base/string_util.h"
namespace logging {
@@ -20,15 +20,8 @@ VlogInfo::VmodulePattern::VmodulePattern(const std::string& pattern)
// If the pattern contains a {forward,back} slash, we assume that
// it's meant to be tested against the entire __FILE__ string.
std::string::size_type first_slash = pattern.find_first_of("\\/");
- if (first_slash != std::string::npos) {
- // The backslash is an escape character for patterns, so we need
- // to escape it. This is okay, because it's highly unlikely that
- // the user would want to match literal *s or ?s. However, we may
- // want to have our own simpler version of MatchPattern() to avoid
- // these sorts of hacks.
- ReplaceSubstringsAfterOffset(&this->pattern, first_slash, "\\", "\\\\");
+ if (first_slash != std::string::npos)
match_target = MATCH_FILE;
- }
}
VlogInfo::VmodulePattern::VmodulePattern()
@@ -93,11 +86,64 @@ int VlogInfo::GetVlogLevel(const base::StringPiece& file) {
vmodule_levels_.begin(); it != vmodule_levels_.end(); ++it) {
base::StringPiece target(
(it->match_target == VmodulePattern::MATCH_FILE) ? file : module);
- if (MatchPattern(target, it->pattern))
+ if (MatchVlogPattern(target, it->pattern))
return it->vlog_level;
}
}
return max_vlog_level_;
}
+bool MatchVlogPattern(const base::StringPiece& string,
+ const base::StringPiece& vlog_pattern) {
+ base::StringPiece p(vlog_pattern);
+ base::StringPiece s(string);
+ // Consume characters until the next star.
+ while (!p.empty() && !s.empty() && (p[0] != '*')) {
+ switch (p[0]) {
+ // A slash (forward or back) must match a slash (forward or back).
+ case '/':
+ case '\\':
+ if ((s[0] != '/') && (s[0] != '\\'))
+ return false;
+ break;
+
+ // A '?' matches anything.
+ case '?':
+ break;
+
+ // Anything else must match literally.
+ default:
+ if (p[0] != s[0])
+ return false;
+ break;
+ }
+ p.remove_prefix(1), s.remove_prefix(1);
+ }
+
+ // An empty pattern here matches only an empty string.
+ if (p.empty())
+ return s.empty();
+
+ // Coalesce runs of consecutive stars. There should be at least
+ // one.
+ while (!p.empty() && (p[0] == '*'))
+ p.remove_prefix(1);
+
+ // Since we moved past the stars, an empty pattern here matches
+ // anything.
+ if (p.empty())
+ return true;
+
+ // Since we moved past the stars and p is non-empty, if some
+ // non-empty substring of s matches p, then we ourselves match.
+ while (!s.empty()) {
+ if (MatchVlogPattern(s, p))
+ return true;
+ s.remove_prefix(1);
+ }
+
+ // Otherwise, we couldn't find a match.
+ return false;
+}
+
} // namespace
diff --git a/base/vlog.h b/base/vlog.h
index 1bdeb24..428b3e1 100644
--- a/base/vlog.h
+++ b/base/vlog.h
@@ -63,6 +63,19 @@ class VlogInfo {
DISALLOW_COPY_AND_ASSIGN(VlogInfo);
};
+// Returns true if the string passed in matches the vlog pattern. The
+// vlog pattern string can contain wildcards like * and ?. ? matches
+// exactly one character while * matches 0 or more characters. Also,
+// as a special case, a / or \ character matches either / or \.
+//
+// Examples:
+// "kh?n" matches "khan" but not "khn" or "khaan"
+// "kh*n" matches "khn", "khan", or even "khaaaaan"
+// "/foo\bar" matches "/foo/bar", "\foo\bar", or "/foo\bar"
+// (disregarding C escaping rules)
+bool MatchVlogPattern(const base::StringPiece& string,
+ const base::StringPiece& vlog_pattern);
+
} // namespace logging
#endif // BASE_VLOG_H_
diff --git a/base/vlog_unittest.cc b/base/vlog_unittest.cc
index c69f9cc..b3ecde6 100644
--- a/base/vlog_unittest.cc
+++ b/base/vlog_unittest.cc
@@ -26,6 +26,54 @@ TEST_F(VlogTest, NoVmodule) {
EXPECT_EQ(5, VlogInfo("5", "").GetVlogLevel("test6"));
}
+TEST_F(VlogTest, MatchVlogPattern) {
+ // Degenerate cases.
+ EXPECT_TRUE(MatchVlogPattern("", ""));
+ EXPECT_TRUE(MatchVlogPattern("", "****"));
+ EXPECT_FALSE(MatchVlogPattern("", "x"));
+ EXPECT_FALSE(MatchVlogPattern("x", ""));
+
+ // Basic.
+ EXPECT_TRUE(MatchVlogPattern("blah", "blah"));
+
+ // ? should match exactly one character.
+ EXPECT_TRUE(MatchVlogPattern("blah", "bl?h"));
+ EXPECT_FALSE(MatchVlogPattern("blh", "bl?h"));
+ EXPECT_FALSE(MatchVlogPattern("blaah", "bl?h"));
+ EXPECT_TRUE(MatchVlogPattern("blah", "?lah"));
+ EXPECT_FALSE(MatchVlogPattern("lah", "?lah"));
+ EXPECT_FALSE(MatchVlogPattern("bblah", "?lah"));
+
+ // * can match any number (even 0) of characters.
+ EXPECT_TRUE(MatchVlogPattern("blah", "bl*h"));
+ EXPECT_TRUE(MatchVlogPattern("blabcdefh", "bl*h"));
+ EXPECT_TRUE(MatchVlogPattern("blh", "bl*h"));
+ EXPECT_TRUE(MatchVlogPattern("blah", "*blah"));
+ EXPECT_TRUE(MatchVlogPattern("ohblah", "*blah"));
+ EXPECT_TRUE(MatchVlogPattern("blah", "blah*"));
+ EXPECT_TRUE(MatchVlogPattern("blahhhh", "blah*"));
+ EXPECT_TRUE(MatchVlogPattern("blahhhh", "blah*"));
+ EXPECT_TRUE(MatchVlogPattern("blah", "*blah*"));
+ EXPECT_TRUE(MatchVlogPattern("blahhhh", "*blah*"));
+ EXPECT_TRUE(MatchVlogPattern("bbbblahhhh", "*blah*"));
+
+ // Multiple *s should work fine.
+ EXPECT_TRUE(MatchVlogPattern("ballaah", "b*la*h"));
+ EXPECT_TRUE(MatchVlogPattern("blah", "b*la*h"));
+ EXPECT_TRUE(MatchVlogPattern("bbbblah", "b*la*h"));
+ EXPECT_TRUE(MatchVlogPattern("blaaah", "b*la*h"));
+
+ // There should be no escaping going on.
+ EXPECT_TRUE(MatchVlogPattern("bl\\ah", "bl\\?h"));
+ EXPECT_FALSE(MatchVlogPattern("bl?h", "bl\\?h"));
+ EXPECT_TRUE(MatchVlogPattern("bl\\aaaah", "bl\\*h"));
+ EXPECT_FALSE(MatchVlogPattern("bl*h", "bl\\*h"));
+
+ // Any slash matches any slash.
+ EXPECT_TRUE(MatchVlogPattern("/b\\lah", "/b\\lah"));
+ EXPECT_TRUE(MatchVlogPattern("\\b/lah", "/b\\lah"));
+}
+
TEST_F(VlogTest, VmoduleBasic) {
const char kVSwitch[] = "-1";
const char kVModuleSwitch[] =
@@ -51,13 +99,14 @@ TEST_F(VlogTest, VmoduleDirs) {
EXPECT_EQ(0, vlog_info.GetVlogLevel("baz/grault/qux.h"));
EXPECT_EQ(0, vlog_info.GetVlogLevel("/baz/grault/qux.cc"));
- EXPECT_EQ(0, vlog_info.GetVlogLevel("baz/grault/qux.cc"));
- EXPECT_EQ(0, vlog_info.GetVlogLevel("baz/grault/blah/qux.cc"));
+ EXPECT_EQ(2, vlog_info.GetVlogLevel("baz/grault/qux.cc"));
+ EXPECT_EQ(2, vlog_info.GetVlogLevel("baz/grault/blah/qux.cc"));
EXPECT_EQ(2, vlog_info.GetVlogLevel("baz\\grault\\qux.cc"));
- EXPECT_EQ(2, vlog_info.GetVlogLevel("baz\\grault\\blah\\qux.cc"));
+ EXPECT_EQ(2, vlog_info.GetVlogLevel("baz\\grault//blah\\qux.cc"));
EXPECT_EQ(0, vlog_info.GetVlogLevel("/foo/bar/baz/quux.cc"));
EXPECT_EQ(3, vlog_info.GetVlogLevel("/foo/bar/baz/quux/grault.cc"));
+ EXPECT_EQ(3, vlog_info.GetVlogLevel("/foo\\bar/baz\\quux/grault.cc"));
EXPECT_EQ(0, vlog_info.GetVlogLevel("foo/bar/test-inl.cc"));
EXPECT_EQ(4, vlog_info.GetVlogLevel("foo/bar/test-inl.h"));