logging/filter: Use std::string_view in ParseFilterString()

Allows avoiding constructing std::string instances, since this only
reads an arbitrary sequence of characters.

We can also make ParseFilterRule() internal, since it doesn't depend on
any private instance state of Filter
This commit is contained in:
Lioncash 2018-07-20 15:42:42 -04:00
parent 7a1a860abe
commit f63ccbd936
2 changed files with 40 additions and 41 deletions

View File

@ -8,39 +8,9 @@
#include "common/string_util.h" #include "common/string_util.h"
namespace Log { namespace Log {
namespace {
Filter::Filter(Level default_level) {
ResetAll(default_level);
}
void Filter::ResetAll(Level level) {
class_levels.fill(level);
}
void Filter::SetClassLevel(Class log_class, Level level) {
class_levels[static_cast<size_t>(log_class)] = level;
}
void Filter::ParseFilterString(const std::string& filter_str) {
auto clause_begin = filter_str.cbegin();
while (clause_begin != filter_str.cend()) {
auto clause_end = std::find(clause_begin, filter_str.cend(), ' ');
// If clause isn't empty
if (clause_end != clause_begin) {
ParseFilterRule(clause_begin, clause_end);
}
if (clause_end != filter_str.cend()) {
// Skip over the whitespace
++clause_end;
}
clause_begin = clause_end;
}
}
template <typename It> template <typename It>
static Level GetLevelByName(const It begin, const It end) { Level GetLevelByName(const It begin, const It end) {
for (u8 i = 0; i < static_cast<u8>(Level::Count); ++i) { for (u8 i = 0; i < static_cast<u8>(Level::Count); ++i) {
const char* level_name = GetLevelName(static_cast<Level>(i)); const char* level_name = GetLevelName(static_cast<Level>(i));
if (Common::ComparePartialString(begin, end, level_name)) { if (Common::ComparePartialString(begin, end, level_name)) {
@ -51,7 +21,7 @@ static Level GetLevelByName(const It begin, const It end) {
} }
template <typename It> template <typename It>
static Class GetClassByName(const It begin, const It end) { Class GetClassByName(const It begin, const It end) {
for (ClassType i = 0; i < static_cast<ClassType>(Class::Count); ++i) { for (ClassType i = 0; i < static_cast<ClassType>(Class::Count); ++i) {
const char* level_name = GetLogClassName(static_cast<Class>(i)); const char* level_name = GetLogClassName(static_cast<Class>(i));
if (Common::ComparePartialString(begin, end, level_name)) { if (Common::ComparePartialString(begin, end, level_name)) {
@ -61,8 +31,8 @@ static Class GetClassByName(const It begin, const It end) {
return Class::Count; return Class::Count;
} }
bool Filter::ParseFilterRule(const std::string::const_iterator begin, template <typename Iterator>
const std::string::const_iterator end) { bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
auto level_separator = std::find(begin, end, ':'); auto level_separator = std::find(begin, end, ':');
if (level_separator == end) { if (level_separator == end) {
LOG_ERROR(Log, "Invalid log filter. Must specify a log level after `:`: {}", LOG_ERROR(Log, "Invalid log filter. Must specify a log level after `:`: {}",
@ -77,7 +47,7 @@ bool Filter::ParseFilterRule(const std::string::const_iterator begin,
} }
if (Common::ComparePartialString(begin, level_separator, "*")) { if (Common::ComparePartialString(begin, level_separator, "*")) {
ResetAll(level); instance.ResetAll(level);
return true; return true;
} }
@ -87,9 +57,40 @@ bool Filter::ParseFilterRule(const std::string::const_iterator begin,
return false; return false;
} }
SetClassLevel(log_class, level); instance.SetClassLevel(log_class, level);
return true; return true;
} }
} // Anonymous namespace
Filter::Filter(Level default_level) {
ResetAll(default_level);
}
void Filter::ResetAll(Level level) {
class_levels.fill(level);
}
void Filter::SetClassLevel(Class log_class, Level level) {
class_levels[static_cast<size_t>(log_class)] = level;
}
void Filter::ParseFilterString(std::string_view filter_view) {
auto clause_begin = filter_view.cbegin();
while (clause_begin != filter_view.cend()) {
auto clause_end = std::find(clause_begin, filter_view.cend(), ' ');
// If clause isn't empty
if (clause_end != clause_begin) {
ParseFilterRule(*this, clause_begin, clause_end);
}
if (clause_end != filter_view.cend()) {
// Skip over the whitespace
++clause_end;
}
clause_begin = clause_end;
}
}
bool Filter::CheckMessage(Class log_class, Level level) const { bool Filter::CheckMessage(Class log_class, Level level) const {
return static_cast<u8>(level) >= static_cast<u8>(class_levels[static_cast<size_t>(log_class)]); return static_cast<u8>(level) >= static_cast<u8>(class_levels[static_cast<size_t>(log_class)]);

View File

@ -6,7 +6,7 @@
#include <array> #include <array>
#include <cstddef> #include <cstddef>
#include <string> #include <string_view>
#include "common/logging/log.h" #include "common/logging/log.h"
namespace Log { namespace Log {
@ -40,9 +40,7 @@ public:
* - `Service:Info` -- Sets the level of Service to Info. * - `Service:Info` -- Sets the level of Service to Info.
* - `Service.FS:Trace` -- Sets the level of the Service.FS class to Trace. * - `Service.FS:Trace` -- Sets the level of the Service.FS class to Trace.
*/ */
void ParseFilterString(const std::string& filter_str); void ParseFilterString(std::string_view filter_view);
bool ParseFilterRule(const std::string::const_iterator start,
const std::string::const_iterator end);
/// Matches class/level combination against the filter, returning true if it passed. /// Matches class/level combination against the filter, returning true if it passed.
bool CheckMessage(Class log_class, Level level) const; bool CheckMessage(Class log_class, Level level) const;