blob: 8c615cb972aaccac1db1fd99cbbbf055baff72b3 [file] [log] [blame]
[email protected]99b7c57f2010-09-29 19:26:361// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/vlog.h"
6
7#include "base/basictypes.h"
[email protected]e11de722010-11-01 20:50:558#include "base/logging.h"
[email protected]99b7c57f2010-09-29 19:26:369#include "base/string_number_conversions.h"
10#include "base/string_split.h"
[email protected]99b7c57f2010-09-29 19:26:3611
12namespace logging {
13
14const int VlogInfo::kDefaultVlogLevel = 0;
15
[email protected]b0d38d4c2010-10-29 00:39:4816VlogInfo::VmodulePattern::VmodulePattern(const std::string& pattern)
17 : pattern(pattern),
18 vlog_level(VlogInfo::kDefaultVlogLevel),
19 match_target(MATCH_MODULE) {
20 // If the pattern contains a {forward,back} slash, we assume that
21 // it's meant to be tested against the entire __FILE__ string.
22 std::string::size_type first_slash = pattern.find_first_of("\\/");
[email protected]e11de722010-11-01 20:50:5523 if (first_slash != std::string::npos)
[email protected]b0d38d4c2010-10-29 00:39:4824 match_target = MATCH_FILE;
[email protected]b0d38d4c2010-10-29 00:39:4825}
26
27VlogInfo::VmodulePattern::VmodulePattern()
28 : vlog_level(VlogInfo::kDefaultVlogLevel),
29 match_target(MATCH_MODULE) {}
30
[email protected]99b7c57f2010-09-29 19:26:3631VlogInfo::VlogInfo(const std::string& v_switch,
32 const std::string& vmodule_switch)
33 : max_vlog_level_(kDefaultVlogLevel) {
34 typedef std::pair<std::string, std::string> KVPair;
[email protected]b0d38d4c2010-10-29 00:39:4835 if (!v_switch.empty() &&
36 !base::StringToInt(v_switch, &max_vlog_level_)) {
[email protected]99b7c57f2010-09-29 19:26:3637 LOG(WARNING) << "Parsed v switch \""
38 << v_switch << "\" as " << max_vlog_level_;
39 }
40 std::vector<KVPair> kv_pairs;
41 if (!base::SplitStringIntoKeyValuePairs(
42 vmodule_switch, '=', ',', &kv_pairs)) {
43 LOG(WARNING) << "Could not fully parse vmodule switch \""
44 << vmodule_switch << "\"";
45 }
46 for (std::vector<KVPair>::const_iterator it = kv_pairs.begin();
47 it != kv_pairs.end(); ++it) {
[email protected]b0d38d4c2010-10-29 00:39:4848 VmodulePattern pattern(it->first);
49 if (!base::StringToInt(it->second, &pattern.vlog_level)) {
[email protected]99b7c57f2010-09-29 19:26:3650 LOG(WARNING) << "Parsed vlog level for \""
51 << it->first << "=" << it->second
[email protected]b0d38d4c2010-10-29 00:39:4852 << "\" as " << pattern.vlog_level;
[email protected]99b7c57f2010-09-29 19:26:3653 }
[email protected]b0d38d4c2010-10-29 00:39:4854 vmodule_levels_.push_back(pattern);
[email protected]99b7c57f2010-09-29 19:26:3655 }
56}
57
[email protected]1889dc1b2010-10-14 22:03:1358VlogInfo::~VlogInfo() {}
59
[email protected]b0d38d4c2010-10-29 00:39:4860namespace {
61
62// Given a path, returns the basename with the extension chopped off
63// (and any -inl suffix). We avoid using FilePath to minimize the
64// number of dependencies the logging system has.
65base::StringPiece GetModule(const base::StringPiece& file) {
66 base::StringPiece module(file);
67 base::StringPiece::size_type last_slash_pos =
68 module.find_last_of("\\/");
69 if (last_slash_pos != base::StringPiece::npos)
70 module.remove_prefix(last_slash_pos + 1);
71 base::StringPiece::size_type extension_start = module.rfind('.');
72 module = module.substr(0, extension_start);
73 static const char kInlSuffix[] = "-inl";
74 static const int kInlSuffixLen = arraysize(kInlSuffix) - 1;
75 if (module.ends_with(kInlSuffix))
76 module.remove_suffix(kInlSuffixLen);
77 return module;
78}
79
80} // namespace
81
[email protected]99b7c57f2010-09-29 19:26:3682int VlogInfo::GetVlogLevel(const base::StringPiece& file) {
83 if (!vmodule_levels_.empty()) {
[email protected]b0d38d4c2010-10-29 00:39:4884 base::StringPiece module(GetModule(file));
[email protected]99b7c57f2010-09-29 19:26:3685 for (std::vector<VmodulePattern>::const_iterator it =
86 vmodule_levels_.begin(); it != vmodule_levels_.end(); ++it) {
[email protected]b0d38d4c2010-10-29 00:39:4887 base::StringPiece target(
88 (it->match_target == VmodulePattern::MATCH_FILE) ? file : module);
[email protected]e11de722010-11-01 20:50:5589 if (MatchVlogPattern(target, it->pattern))
[email protected]b0d38d4c2010-10-29 00:39:4890 return it->vlog_level;
[email protected]99b7c57f2010-09-29 19:26:3691 }
92 }
93 return max_vlog_level_;
94}
95
[email protected]e11de722010-11-01 20:50:5596bool MatchVlogPattern(const base::StringPiece& string,
97 const base::StringPiece& vlog_pattern) {
98 base::StringPiece p(vlog_pattern);
99 base::StringPiece s(string);
100 // Consume characters until the next star.
101 while (!p.empty() && !s.empty() && (p[0] != '*')) {
102 switch (p[0]) {
103 // A slash (forward or back) must match a slash (forward or back).
104 case '/':
105 case '\\':
106 if ((s[0] != '/') && (s[0] != '\\'))
107 return false;
108 break;
109
110 // A '?' matches anything.
111 case '?':
112 break;
113
114 // Anything else must match literally.
115 default:
116 if (p[0] != s[0])
117 return false;
118 break;
119 }
120 p.remove_prefix(1), s.remove_prefix(1);
121 }
122
123 // An empty pattern here matches only an empty string.
124 if (p.empty())
125 return s.empty();
126
127 // Coalesce runs of consecutive stars. There should be at least
128 // one.
129 while (!p.empty() && (p[0] == '*'))
130 p.remove_prefix(1);
131
132 // Since we moved past the stars, an empty pattern here matches
133 // anything.
134 if (p.empty())
135 return true;
136
137 // Since we moved past the stars and p is non-empty, if some
138 // non-empty substring of s matches p, then we ourselves match.
139 while (!s.empty()) {
140 if (MatchVlogPattern(s, p))
141 return true;
142 s.remove_prefix(1);
143 }
144
145 // Otherwise, we couldn't find a match.
146 return false;
147}
148
[email protected]99b7c57f2010-09-29 19:26:36149} // namespace