Seregon/ShadPKG

A tool for deriving PKG packet encryption keys for ps4 written in c++

C++/47.3 KB/No license
common/logging/filter.cpp
ShadPKG / common / logging / filter.cpp
1// SPDX-FileCopyrightText: Copyright 2014 Citra Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3 
4#include <algorithm>
5 
6#include "common/assert.h"
7#include "common/logging/filter.h"
8 
9namespace Common::Log {
10namespace {
11template <typename It>
12Level GetLevelByName(const It begin, const It end) {
13 for (u8 i = 0; i < static_cast<u8>(Level::Count); ++i) {
14 const char* level_name = GetLevelName(static_cast<Level>(i));
15 if (std::string_view(begin, end).compare(level_name) == 0) {
16 return static_cast<Level>(i);
17 }
18 }
19 return Level::Count;
20}
21 
22template <typename It>
23Class GetClassByName(const It begin, const It end) {
24 for (u8 i = 0; i < static_cast<u8>(Class::Count); ++i) {
25 const char* level_name = GetLogClassName(static_cast<Class>(i));
26 if (std::string_view(begin, end).compare(level_name) == 0) {
27 return static_cast<Class>(i);
28 }
29 }
30 return Class::Count;
31}
32 
33template <typename Iterator>
34bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
35 auto level_separator = std::find(begin, end, ':');
36 if (level_separator == end) {
37 LOG_ERROR(Log, "Invalid log filter. Must specify a log level after `:`: {}",
38 std::string_view(begin, end));
39 return false;
40 }
41 
42 const Level level = GetLevelByName(level_separator + 1, end);
43 if (level == Level::Count) {
44 LOG_ERROR(Log, "Unknown log level in filter: {}", std::string_view(begin, end));
45 return false;
46 }
47 
48 if (std::string_view(begin, level_separator).compare("*") == 0) {
49 instance.ResetAll(level);
50 return true;
51 }
52 
53 const Class log_class = GetClassByName(begin, level_separator);
54 if (log_class == Class::Count) {
55 LOG_ERROR(Log, "Unknown log class in filter: {}", std::string(begin, end));
56 return false;
57 }
58 
59 instance.SetClassLevel(log_class, level);
60 return true;
61}
62} // Anonymous namespace
63 
64/// Macro listing all log classes. Code should define CLS and SUB as desired before invoking this.
65#define ALL_LOG_CLASSES() \
66 CLS(Log) \
67 CLS(Common) \
68 SUB(Common, Filesystem) \
69 SUB(Common, Memory) \
70 CLS(Core) \
71 SUB(Core, Linker) \
72 SUB(Core, Devices) \
73 CLS(Config) \
74 CLS(Debug) \
75 CLS(Kernel) \
76 SUB(Kernel, Pthread) \
77 SUB(Kernel, Vmm) \
78 SUB(Kernel, Fs) \
79 SUB(Kernel, Event) \
80 SUB(Kernel, Sce) \
81 CLS(Lib) \
82 SUB(Lib, LibC) \
83 SUB(Lib, Kernel) \
84 SUB(Lib, Pad) \
85 SUB(Lib, GnmDriver) \
86 SUB(Lib, SystemService) \
87 SUB(Lib, UserService) \
88 SUB(Lib, VideoOut) \
89 SUB(Lib, CommonDlg) \
90 SUB(Lib, MsgDlg) \
91 SUB(Lib, AudioOut) \
92 SUB(Lib, AudioIn) \
93 SUB(Lib, Net) \
94 SUB(Lib, NetCtl) \
95 SUB(Lib, SaveData) \
96 SUB(Lib, SaveDataDialog) \
97 SUB(Lib, Http) \
98 SUB(Lib, Http2) \
99 SUB(Lib, Ssl) \
100 SUB(Lib, Ssl2) \
101 SUB(Lib, SysModule) \
102 SUB(Lib, Move) \
103 SUB(Lib, NpCommon) \
104 SUB(Lib, NpManager) \
105 SUB(Lib, NpScore) \
106 SUB(Lib, NpTrophy) \
107 SUB(Lib, NpWebApi) \
108 SUB(Lib, Screenshot) \
109 SUB(Lib, LibCInternal) \
110 SUB(Lib, AppContent) \
111 SUB(Lib, Rtc) \
112 SUB(Lib, DiscMap) \
113 SUB(Lib, Png) \
114 SUB(Lib, Jpeg) \
115 SUB(Lib, PlayGo) \
116 SUB(Lib, PlayGoDialog) \
117 SUB(Lib, Random) \
118 SUB(Lib, Usbd) \
119 SUB(Lib, Ajm) \
120 SUB(Lib, ErrorDialog) \
121 SUB(Lib, ImeDialog) \
122 SUB(Lib, AvPlayer) \
123 SUB(Lib, Ngs2) \
124 SUB(Lib, Audio3d) \
125 SUB(Lib, Ime) \
126 SUB(Lib, GameLiveStreaming) \
127 SUB(Lib, Remoteplay) \
128 SUB(Lib, SharePlay) \
129 SUB(Lib, Fiber) \
130 SUB(Lib, Vdec2) \
131 SUB(Lib, Videodec) \
132 SUB(Lib, RazorCpu) \
133 SUB(Lib, Mouse) \
134 SUB(Lib, WebBrowserDialog) \
135 SUB(Lib, NpParty) \
136 SUB(Lib, Zlib) \
137 CLS(Frontend) \
138 CLS(Render) \
139 SUB(Render, Vulkan) \
140 SUB(Render, Recompiler) \
141 CLS(ImGui) \
142 CLS(Input) \
143 CLS(Tty) \
144 CLS(Loader)
145 
146// GetClassName is a macro defined by Windows.h, grrr...
147const char* GetLogClassName(Class log_class) {
148 switch (log_class) {
149#define CLS(x) \
150 case Class::x: \
151 return #x;
152#define SUB(x, y) \
153 case Class::x##_##y: \
154 return #x "." #y;
155 ALL_LOG_CLASSES()
156#undef CLS
157#undef SUB
158 case Class::Count:
159 default:
160 break;
161 }
162 UNREACHABLE();
163}
164 
165const char* GetLevelName(Level log_level) {
166#define LVL(x) \
167 case Level::x: \
168 return #x
169 switch (log_level) {
170 LVL(Trace);
171 LVL(Debug);
172 LVL(Info);
173 LVL(Warning);
174 LVL(Error);
175 LVL(Critical);
176 case Level::Count:
177 default:
178 break;
179 }
180#undef LVL
181 UNREACHABLE();
182}
183 
184Filter::Filter(Level default_level) {
185 ResetAll(default_level);
186}
187 
188void Filter::ResetAll(Level level) {
189 class_levels.fill(level);
190}
191 
192void Filter::SetClassLevel(Class log_class, Level level) {
193 class_levels[static_cast<std::size_t>(log_class)] = level;
194}
195 
196void Filter::ParseFilterString(std::string_view filter_view) {
197 auto clause_begin = filter_view.cbegin();
198 while (clause_begin != filter_view.cend()) {
199 auto clause_end = std::find(clause_begin, filter_view.cend(), ' ');
200 
201 // If clause isn't empty
202 if (clause_end != clause_begin) {
203 ParseFilterRule(*this, clause_begin, clause_end);
204 }
205 
206 if (clause_end != filter_view.cend()) {
207 // Skip over the whitespace
208 ++clause_end;
209 }
210 clause_begin = clause_end;
211 }
212}
213 
214bool Filter::CheckMessage(Class log_class, Level level) const {
215 return static_cast<u8>(level) >=
216 static_cast<u8>(class_levels[static_cast<std::size_t>(log_class)]);
217}
218 
219bool Filter::IsDebug() const {
220 return std::any_of(class_levels.begin(), class_levels.end(), [](const Level& l) {
221 return static_cast<u8>(l) <= static_cast<u8>(Level::Debug);
222 });
223}
224 
225} // namespace Common::Log
226