filter.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <algorithm>
  5. #include "common/logging/backend.h"
  6. #include "common/logging/filter.h"
  7. #include "common/string_util.h"
  8. namespace Log {
  9. Filter::Filter(Level default_level) {
  10. ResetAll(default_level);
  11. }
  12. void Filter::ResetAll(Level level) {
  13. class_levels.fill(level);
  14. }
  15. void Filter::SetClassLevel(Class log_class, Level level) {
  16. class_levels[static_cast<size_t>(log_class)] = level;
  17. }
  18. void Filter::ParseFilterString(const std::string& filter_str) {
  19. auto clause_begin = filter_str.cbegin();
  20. while (clause_begin != filter_str.cend()) {
  21. auto clause_end = std::find(clause_begin, filter_str.cend(), ' ');
  22. // If clause isn't empty
  23. if (clause_end != clause_begin) {
  24. ParseFilterRule(clause_begin, clause_end);
  25. }
  26. if (clause_end != filter_str.cend()) {
  27. // Skip over the whitespace
  28. ++clause_end;
  29. }
  30. clause_begin = clause_end;
  31. }
  32. }
  33. template <typename It>
  34. static Level GetLevelByName(const It begin, const It end) {
  35. for (u8 i = 0; i < static_cast<u8>(Level::Count); ++i) {
  36. const char* level_name = GetLevelName(static_cast<Level>(i));
  37. if (Common::ComparePartialString(begin, end, level_name)) {
  38. return static_cast<Level>(i);
  39. }
  40. }
  41. return Level::Count;
  42. }
  43. template <typename It>
  44. static Class GetClassByName(const It begin, const It end) {
  45. for (ClassType i = 0; i < static_cast<ClassType>(Class::Count); ++i) {
  46. const char* level_name = GetLogClassName(static_cast<Class>(i));
  47. if (Common::ComparePartialString(begin, end, level_name)) {
  48. return static_cast<Class>(i);
  49. }
  50. }
  51. return Class::Count;
  52. }
  53. bool Filter::ParseFilterRule(const std::string::const_iterator begin,
  54. const std::string::const_iterator end) {
  55. auto level_separator = std::find(begin, end, ':');
  56. if (level_separator == end) {
  57. LOG_ERROR(Log, "Invalid log filter. Must specify a log level after `:`: {}",
  58. std::string(begin, end));
  59. return false;
  60. }
  61. const Level level = GetLevelByName(level_separator + 1, end);
  62. if (level == Level::Count) {
  63. LOG_ERROR(Log, "Unknown log level in filter: {}", std::string(begin, end));
  64. return false;
  65. }
  66. if (Common::ComparePartialString(begin, level_separator, "*")) {
  67. ResetAll(level);
  68. return true;
  69. }
  70. const Class log_class = GetClassByName(begin, level_separator);
  71. if (log_class == Class::Count) {
  72. LOG_ERROR(Log, "Unknown log class in filter: {}", std::string(begin, end));
  73. return false;
  74. }
  75. SetClassLevel(log_class, level);
  76. return true;
  77. }
  78. bool Filter::CheckMessage(Class log_class, Level level) const {
  79. return static_cast<u8>(level) >= static_cast<u8>(class_levels[static_cast<size_t>(log_class)]);
  80. }
  81. bool Filter::IsDebug() const {
  82. return std::any_of(class_levels.begin(), class_levels.end(), [](const Level& l) {
  83. return static_cast<u8>(l) <= static_cast<u8>(Level::Debug);
  84. });
  85. }
  86. } // namespace Log