mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Merge pull request #5823 from SachinVin/dyn
Android: Backport easy stuff
This commit is contained in:
		
						commit
						6183b5d76c
					
				
					 43 changed files with 1052 additions and 365 deletions
				
			
		|  | @ -26,6 +26,10 @@ | |||
| 
 | ||||
| namespace Log { | ||||
| 
 | ||||
| Filter filter; | ||||
| void SetGlobalFilter(const Filter& f) { | ||||
|     filter = f; | ||||
| } | ||||
| /**
 | ||||
|  * Static state as a singleton. | ||||
|  */ | ||||
|  | @ -58,14 +62,6 @@ public: | |||
|         backends.erase(it, backends.end()); | ||||
|     } | ||||
| 
 | ||||
|     const Filter& GetGlobalFilter() const { | ||||
|         return filter; | ||||
|     } | ||||
| 
 | ||||
|     void SetGlobalFilter(const Filter& f) { | ||||
|         filter = f; | ||||
|     } | ||||
| 
 | ||||
|     Backend* GetBackend(std::string_view backend_name) { | ||||
|         const auto it = | ||||
|             std::find_if(backends.begin(), backends.end(), | ||||
|  | @ -144,6 +140,10 @@ void ColorConsoleBackend::Write(const Entry& entry) { | |||
|     PrintColoredMessage(entry); | ||||
| } | ||||
| 
 | ||||
| void LogcatBackend::Write(const Entry& entry) { | ||||
|     PrintMessageToLogcat(entry); | ||||
| } | ||||
| 
 | ||||
| FileBackend::FileBackend(const std::string& filename) : bytes_written(0) { | ||||
|     if (FileUtil::Exists(filename + ".old.txt")) { | ||||
|         FileUtil::Delete(filename + ".old.txt"); | ||||
|  | @ -283,10 +283,6 @@ const char* GetLevelName(Level log_level) { | |||
|     return "Invalid"; | ||||
| } | ||||
| 
 | ||||
| void SetGlobalFilter(const Filter& filter) { | ||||
|     Impl::Instance().SetGlobalFilter(filter); | ||||
| } | ||||
| 
 | ||||
| void AddBackend(std::unique_ptr<Backend> backend) { | ||||
|     Impl::Instance().AddBackend(std::move(backend)); | ||||
| } | ||||
|  | @ -303,10 +299,6 @@ void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, | |||
|                        unsigned int line_num, const char* function, const char* format, | ||||
|                        const fmt::format_args& args) { | ||||
|     auto& instance = Impl::Instance(); | ||||
|     const auto& filter = instance.GetGlobalFilter(); | ||||
|     if (!filter.CheckMessage(log_class, log_level)) | ||||
|         return; | ||||
| 
 | ||||
|     instance.PushEntry(log_class, log_level, filename, line_num, function, | ||||
|                        fmt::vformat(format, args)); | ||||
| } | ||||
|  |  | |||
|  | @ -14,8 +14,6 @@ | |||
| 
 | ||||
| namespace Log { | ||||
| 
 | ||||
| class Filter; | ||||
| 
 | ||||
| /**
 | ||||
|  * A log entry. Log entries are store in a structured format to permit more varied output | ||||
|  * formatting on different frontends, as well as facilitating filtering and aggregation. | ||||
|  | @ -83,6 +81,21 @@ public: | |||
|     void Write(const Entry& entry) override; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * Backend that writes to the Android logcat | ||||
|  */ | ||||
| class LogcatBackend : public Backend { | ||||
| public: | ||||
|     static const char* Name() { | ||||
|         return "logcat"; | ||||
|     } | ||||
| 
 | ||||
|     const char* GetName() const override { | ||||
|         return Name(); | ||||
|     } | ||||
|     void Write(const Entry& entry) override; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * Backend that writes to a file passed into the constructor | ||||
|  */ | ||||
|  | @ -136,10 +149,4 @@ const char* GetLogClassName(Class log_class); | |||
|  */ | ||||
| const char* GetLevelName(Level log_level); | ||||
| 
 | ||||
| /**
 | ||||
|  * The global filter will prevent any messages from even being processed if they are filtered. Each | ||||
|  * backend can have a filter, but if the level is lower than the global filter, the backend will | ||||
|  * never get the message | ||||
|  */ | ||||
| void SetGlobalFilter(const Filter& filter); | ||||
| } // namespace Log
 | ||||
|  |  | |||
|  | @ -9,43 +9,4 @@ | |||
| #include <string_view> | ||||
| #include "common/logging/log.h" | ||||
| 
 | ||||
| namespace Log { | ||||
| 
 | ||||
| /**
 | ||||
|  * Implements a log message filter which allows different log classes to have different minimum | ||||
|  * severity levels. The filter can be changed at runtime and can be parsed from a string to allow | ||||
|  * editing via the interface or loading from a configuration file. | ||||
|  */ | ||||
| class Filter { | ||||
| public: | ||||
|     /// Initializes the filter with all classes having `default_level` as the minimum level.
 | ||||
|     explicit Filter(Level default_level = Level::Info); | ||||
| 
 | ||||
|     /// Resets the filter so that all classes have `level` as the minimum displayed level.
 | ||||
|     void ResetAll(Level level); | ||||
|     /// Sets the minimum level of `log_class` (and not of its subclasses) to `level`.
 | ||||
|     void SetClassLevel(Class log_class, Level level); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Parses a filter string and applies it to this filter. | ||||
|      * | ||||
|      * A filter string consists of a space-separated list of filter rules, each of the format | ||||
|      * `<class>:<level>`. `<class>` is a log class name, with subclasses separated using periods. | ||||
|      * `*` is allowed as a class name and will reset all filters to the specified level. `<level>` | ||||
|      * a severity level name which will be set as the minimum logging level of the matched classes. | ||||
|      * Rules are applied left to right, with each rule overriding previous ones in the sequence. | ||||
|      * | ||||
|      * A few examples of filter rules: | ||||
|      *  - `*:Info` -- Resets the level of all classes to Info. | ||||
|      *  - `Service:Info` -- Sets the level of Service to Info. | ||||
|      *  - `Service.FS:Trace` -- Sets the level of the Service.FS class to Trace. | ||||
|      */ | ||||
|     void ParseFilterString(std::string_view filter_view); | ||||
| 
 | ||||
|     /// Matches class/level combination against the filter, returning true if it passed.
 | ||||
|     bool CheckMessage(Class log_class, Level level) const; | ||||
| 
 | ||||
| private: | ||||
|     std::array<Level, static_cast<std::size_t>(Class::Count)> class_levels; | ||||
| }; | ||||
| } // namespace Log
 | ||||
| namespace Log {} // namespace Log
 | ||||
|  |  | |||
|  | @ -4,13 +4,14 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <array> | ||||
| #include <fmt/format.h> | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| namespace Log { | ||||
| 
 | ||||
| // trims up to and including the last of ../, ..\, src/, src\ in a string
 | ||||
| constexpr const char* TrimSourcePath(std::string_view source) { | ||||
| inline const char* TrimSourcePath(std::string_view source) { | ||||
|     const auto rfind = [source](const std::string_view match) { | ||||
|         return source.rfind(match) == source.npos ? 0 : (source.rfind(match) + match.size()); | ||||
|     }; | ||||
|  | @ -113,6 +114,47 @@ enum class Class : ClassType { | |||
|     Count              ///< Total number of logging classes
 | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * Implements a log message filter which allows different log classes to have different minimum | ||||
|  * severity levels. The filter can be changed at runtime and can be parsed from a string to allow | ||||
|  * editing via the interface or loading from a configuration file. | ||||
|  */ | ||||
| class Filter { | ||||
| public: | ||||
|     /// Initializes the filter with all classes having `default_level` as the minimum level.
 | ||||
|     explicit Filter(Level default_level = Level::Info); | ||||
| 
 | ||||
|     /// Resets the filter so that all classes have `level` as the minimum displayed level.
 | ||||
|     void ResetAll(Level level); | ||||
|     /// Sets the minimum level of `log_class` (and not of its subclasses) to `level`.
 | ||||
|     void SetClassLevel(Class log_class, Level level); | ||||
| 
 | ||||
|     /**
 | ||||
|      * Parses a filter string and applies it to this filter. | ||||
|      * | ||||
|      * A filter string consists of a space-separated list of filter rules, each of the format | ||||
|      * `<class>:<level>`. `<class>` is a log class name, with subclasses separated using periods. | ||||
|      * `*` is allowed as a class name and will reset all filters to the specified level. `<level>` | ||||
|      * a severity level name which will be set as the minimum logging level of the matched classes. | ||||
|      * Rules are applied left to right, with each rule overriding previous ones in the sequence. | ||||
|      * | ||||
|      * A few examples of filter rules: | ||||
|      *  - `*:Info` -- Resets the level of all classes to Info. | ||||
|      *  - `Service:Info` -- Sets the level of Service to Info. | ||||
|      *  - `Service.FS:Trace` -- Sets the level of the Service.FS class to Trace. | ||||
|      */ | ||||
|     void ParseFilterString(std::string_view filter_view); | ||||
| 
 | ||||
|     /// Matches class/level combination against the filter, returning true if it passed.
 | ||||
|     bool CheckMessage(Class log_class, Level level) const; | ||||
| 
 | ||||
| private: | ||||
|     std::array<Level, static_cast<std::size_t>(Class::Count)> class_levels; | ||||
| }; | ||||
| extern Filter filter; | ||||
| 
 | ||||
| void SetGlobalFilter(const Filter& f); | ||||
| 
 | ||||
| /// Logs a message to the global logger, using fmt
 | ||||
| void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, | ||||
|                        unsigned int line_num, const char* function, const char* format, | ||||
|  | @ -121,6 +163,9 @@ void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, | |||
| template <typename... Args> | ||||
| void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsigned int line_num, | ||||
|                    const char* function, const char* format, const Args&... args) { | ||||
|     if (!filter.CheckMessage(log_class, log_level)) | ||||
|         return; | ||||
| 
 | ||||
|     FmtLogMessageImpl(log_class, log_level, filename, line_num, function, format, | ||||
|                       fmt::make_format_args(args...)); | ||||
| } | ||||
|  |  | |||
|  | @ -34,13 +34,7 @@ std::string FormatLogMessage(const Entry& entry) { | |||
| 
 | ||||
| void PrintMessage(const Entry& entry) { | ||||
|     const auto str = FormatLogMessage(entry).append(1, '\n'); | ||||
| #ifdef ANDROID | ||||
|     // Android's log level enum are offset by '2'
 | ||||
|     const int android_log_level = static_cast<int>(entry.log_level) + 2; | ||||
|     __android_log_print(android_log_level, "CitraNative", "%s", str.c_str()); | ||||
| #else | ||||
|     fputs(str.c_str(), stderr); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void PrintColoredMessage(const Entry& entry) { | ||||
|  | @ -78,7 +72,7 @@ void PrintColoredMessage(const Entry& entry) { | |||
|     } | ||||
| 
 | ||||
|     SetConsoleTextAttribute(console_handle, color); | ||||
| #elif !defined(ANDROID) | ||||
| #else | ||||
| #define ESC "\x1b" | ||||
|     const char* color = ""; | ||||
|     switch (entry.log_level) { | ||||
|  | @ -111,9 +105,40 @@ void PrintColoredMessage(const Entry& entry) { | |||
| 
 | ||||
| #ifdef _WIN32 | ||||
|     SetConsoleTextAttribute(console_handle, original_info.wAttributes); | ||||
| #elif !defined(ANDROID) | ||||
| #else | ||||
|     fputs(ESC "[0m", stderr); | ||||
| #undef ESC | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| void PrintMessageToLogcat(const Entry& entry) { | ||||
| #ifdef ANDROID | ||||
|     const auto str = FormatLogMessage(entry); | ||||
| 
 | ||||
|     android_LogPriority android_log_priority; | ||||
|     switch (entry.log_level) { | ||||
|     case Level::Trace: | ||||
|         android_log_priority = ANDROID_LOG_VERBOSE; | ||||
|         break; | ||||
|     case Level::Debug: | ||||
|         android_log_priority = ANDROID_LOG_DEBUG; | ||||
|         break; | ||||
|     case Level::Info: | ||||
|         android_log_priority = ANDROID_LOG_INFO; | ||||
|         break; | ||||
|     case Level::Warning: | ||||
|         android_log_priority = ANDROID_LOG_WARN; | ||||
|         break; | ||||
|     case Level::Error: | ||||
|         android_log_priority = ANDROID_LOG_ERROR; | ||||
|         break; | ||||
|     case Level::Critical: | ||||
|         android_log_priority = ANDROID_LOG_FATAL; | ||||
|         break; | ||||
|     case Level::Count: | ||||
|         UNREACHABLE(); | ||||
|     } | ||||
|     __android_log_print(android_log_priority, "CitraNative", "%s", str.c_str()); | ||||
| #endif | ||||
| } | ||||
| } // namespace Log
 | ||||
|  |  | |||
|  | @ -17,4 +17,6 @@ std::string FormatLogMessage(const Entry& entry); | |||
| void PrintMessage(const Entry& entry); | ||||
| /// Prints the same message as `PrintMessage`, but colored according to the severity level.
 | ||||
| void PrintColoredMessage(const Entry& entry); | ||||
| /// Formats and prints a log entry to the android logcat.
 | ||||
| void PrintMessageToLogcat(const Entry& entry); | ||||
| } // namespace Log
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue