mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	Merge pull request #4575 from BreadFish64/android6
android: add logging
This commit is contained in:
		
						commit
						fd7730e7c8
					
				
					 18 changed files with 381 additions and 42 deletions
				
			
		|  | @ -85,4 +85,88 @@ SpacesInSquareBrackets: false | ||||||
| Standard:        Cpp11 | Standard:        Cpp11 | ||||||
| TabWidth:        4 | TabWidth:        4 | ||||||
| UseTab:          Never | UseTab:          Never | ||||||
|  | --- | ||||||
|  | Language:        Java | ||||||
|  | # BasedOnStyle:  LLVM | ||||||
|  | AccessModifierOffset: -4 | ||||||
|  | AlignAfterOpenBracket: Align | ||||||
|  | AlignConsecutiveAssignments: false | ||||||
|  | AlignConsecutiveDeclarations: false | ||||||
|  | AlignEscapedNewlinesLeft: false | ||||||
|  | AlignOperands: true | ||||||
|  | AlignTrailingComments: true | ||||||
|  | AllowAllParametersOfDeclarationOnNextLine: true | ||||||
|  | AllowShortBlocksOnASingleLine: false | ||||||
|  | AllowShortCaseLabelsOnASingleLine: false | ||||||
|  | AllowShortFunctionsOnASingleLine: Empty | ||||||
|  | AllowShortIfStatementsOnASingleLine: false | ||||||
|  | AllowShortLoopsOnASingleLine: false | ||||||
|  | AlwaysBreakAfterDefinitionReturnType: None | ||||||
|  | AlwaysBreakAfterReturnType: None | ||||||
|  | AlwaysBreakBeforeMultilineStrings: false | ||||||
|  | AlwaysBreakTemplateDeclarations: true | ||||||
|  | BinPackArguments: true | ||||||
|  | BinPackParameters: true | ||||||
|  | BraceWrapping: | ||||||
|  |   AfterClass:      false | ||||||
|  |   AfterControlStatement: false | ||||||
|  |   AfterEnum:       false | ||||||
|  |   AfterFunction:   false | ||||||
|  |   AfterNamespace:  false | ||||||
|  |   AfterObjCDeclaration: false | ||||||
|  |   AfterStruct:     false | ||||||
|  |   AfterUnion:      false | ||||||
|  |   BeforeCatch:     false | ||||||
|  |   BeforeElse:      false | ||||||
|  |   IndentBraces:    false | ||||||
|  | BreakBeforeBinaryOperators: None | ||||||
|  | BreakBeforeBraces: Attach | ||||||
|  | BreakBeforeTernaryOperators: true | ||||||
|  | BreakConstructorInitializersBeforeComma: false | ||||||
|  | ColumnLimit:     100 | ||||||
|  | ConstructorInitializerAllOnOneLineOrOnePerLine: false | ||||||
|  | ConstructorInitializerIndentWidth: 4 | ||||||
|  | ContinuationIndentWidth: 4 | ||||||
|  | Cpp11BracedListStyle: true | ||||||
|  | DerivePointerAlignment: false | ||||||
|  | DisableFormat:   false | ||||||
|  | IncludeCategories: | ||||||
|  |   - Regex:           '^\<[^Q][^/.>]*\>' | ||||||
|  |     Priority:        -2 | ||||||
|  |   - Regex:           '^\<' | ||||||
|  |     Priority:        -1 | ||||||
|  |   - Regex:           '^\"' | ||||||
|  |     Priority:        0 | ||||||
|  | IndentCaseLabels: false | ||||||
|  | IndentWidth:     4 | ||||||
|  | IndentWrappedFunctionNames: false | ||||||
|  | KeepEmptyLinesAtTheStartOfBlocks: true | ||||||
|  | MacroBlockBegin: '' | ||||||
|  | MacroBlockEnd:   '' | ||||||
|  | MaxEmptyLinesToKeep: 1 | ||||||
|  | NamespaceIndentation: None | ||||||
|  | ObjCBlockIndentWidth: 2 | ||||||
|  | ObjCSpaceAfterProperty: false | ||||||
|  | ObjCSpaceBeforeProtocolList: true | ||||||
|  | PenaltyBreakBeforeFirstCallParameter: 19 | ||||||
|  | PenaltyBreakComment: 300 | ||||||
|  | PenaltyBreakFirstLessLess: 120 | ||||||
|  | PenaltyBreakString: 1000 | ||||||
|  | PenaltyExcessCharacter: 1000000 | ||||||
|  | PenaltyReturnTypeOnItsOwnLine: 150 | ||||||
|  | PointerAlignment: Left | ||||||
|  | ReflowComments:  true | ||||||
|  | SortIncludes:    true | ||||||
|  | SpaceAfterCStyleCast: false | ||||||
|  | SpaceBeforeAssignmentOperators: true | ||||||
|  | SpaceBeforeParens: ControlStatements | ||||||
|  | SpaceInEmptyParentheses: false | ||||||
|  | SpacesBeforeTrailingComments: 1 | ||||||
|  | SpacesInAngles:  false | ||||||
|  | SpacesInContainerLiterals: true | ||||||
|  | SpacesInCStyleCastParentheses: false | ||||||
|  | SpacesInParentheses: false | ||||||
|  | SpacesInSquareBrackets: false | ||||||
|  | TabWidth:        4 | ||||||
|  | UseTab:          Never | ||||||
| ... | ... | ||||||
|  |  | ||||||
|  | @ -1,10 +1,16 @@ | ||||||
| cmake_minimum_required(VERSION 3.8) | cmake_minimum_required(VERSION 3.8) | ||||||
| 
 | 
 | ||||||
| add_library(citra-android SHARED | add_library(citra-android SHARED | ||||||
|             dummy.cpp |             logging/log.cpp | ||||||
|  |             logging/logcat_backend.cpp | ||||||
|  |             logging/logcat_backend.h | ||||||
|  |             native_interface.cpp | ||||||
|  |             native_interface.h | ||||||
|  |             ui/main/main_activity.cpp | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
| # find Android's log library | # find Android's log library | ||||||
| find_library(log-lib log) | find_library(log-lib log) | ||||||
| 
 | 
 | ||||||
| target_link_libraries(citra-android ${log-lib} core common inih) | target_link_libraries(citra-android ${log-lib} core common inih) | ||||||
|  | target_include_directories(citra-android PRIVATE "../../../../../" "./") | ||||||
|  |  | ||||||
|  | @ -1,3 +0,0 @@ | ||||||
| int dummy(int a, int b) { |  | ||||||
|     return a + b; |  | ||||||
| } |  | ||||||
							
								
								
									
										15
									
								
								src/android/app/src/main/cpp/logging/log.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/android/app/src/main/cpp/logging/log.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | #include "common/logging/log.h" | ||||||
|  | #include "native_interface.h" | ||||||
|  | 
 | ||||||
|  | namespace Log { | ||||||
|  | extern "C" { | ||||||
|  | JNICALL void Java_org_citra_1emu_citra_LOG_logEntry(JNIEnv* env, jclass type, jint level, | ||||||
|  |                                                     jstring file_name, jint line_number, | ||||||
|  |                                                     jstring function, jstring msg) { | ||||||
|  |     using CitraJNI::GetJString; | ||||||
|  |     FmtLogMessage(Class::Frontend, static_cast<Level>(level), GetJString(env, file_name).data(), | ||||||
|  |                   static_cast<unsigned int>(line_number), GetJString(env, function).data(), | ||||||
|  |                   GetJString(env, msg).data()); | ||||||
|  | } | ||||||
|  | } | ||||||
|  | } // namespace Log
 | ||||||
							
								
								
									
										38
									
								
								src/android/app/src/main/cpp/logging/logcat_backend.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/android/app/src/main/cpp/logging/logcat_backend.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,38 @@ | ||||||
|  | // Copyright 2019 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #include <android/log.h> | ||||||
|  | #include "common/assert.h" | ||||||
|  | #include "common/logging/text_formatter.h" | ||||||
|  | #include "logcat_backend.h" | ||||||
|  | 
 | ||||||
|  | namespace Log { | ||||||
|  | void LogcatBackend::Write(const Entry& entry) { | ||||||
|  |     android_LogPriority priority; | ||||||
|  |     switch (entry.log_level) { | ||||||
|  |     case Level::Trace: | ||||||
|  |         priority = ANDROID_LOG_VERBOSE; | ||||||
|  |         break; | ||||||
|  |     case Level::Debug: | ||||||
|  |         priority = ANDROID_LOG_DEBUG; | ||||||
|  |         break; | ||||||
|  |     case Level::Info: | ||||||
|  |         priority = ANDROID_LOG_INFO; | ||||||
|  |         break; | ||||||
|  |     case Level::Warning: | ||||||
|  |         priority = ANDROID_LOG_WARN; | ||||||
|  |         break; | ||||||
|  |     case Level::Error: | ||||||
|  |         priority = ANDROID_LOG_ERROR; | ||||||
|  |         break; | ||||||
|  |     case Level::Critical: | ||||||
|  |         priority = ANDROID_LOG_FATAL; | ||||||
|  |         break; | ||||||
|  |     case Level::Count: | ||||||
|  |         UNREACHABLE(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     __android_log_print(priority, "citra", "%s\n", FormatLogMessage(entry).c_str()); | ||||||
|  | } | ||||||
|  | } // namespace Log
 | ||||||
							
								
								
									
										22
									
								
								src/android/app/src/main/cpp/logging/logcat_backend.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/android/app/src/main/cpp/logging/logcat_backend.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | ||||||
|  | // Copyright 2019 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include "common/logging/backend.h" | ||||||
|  | 
 | ||||||
|  | namespace Log { | ||||||
|  | class LogcatBackend : public Backend { | ||||||
|  | public: | ||||||
|  |     static const char* Name() { | ||||||
|  |         return "Logcat"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const char* GetName() const override { | ||||||
|  |         return Name(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     void Write(const Entry& entry) override; | ||||||
|  | }; | ||||||
|  | } // namespace Log
 | ||||||
							
								
								
									
										22
									
								
								src/android/app/src/main/cpp/native_interface.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/android/app/src/main/cpp/native_interface.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | ||||||
|  | // Copyright 2019 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #include "native_interface.h" | ||||||
|  | 
 | ||||||
|  | namespace CitraJNI { | ||||||
|  | jint JNI_OnLoad(JavaVM* vm, void* reserved) { | ||||||
|  |     return JNI_VERSION_1_6; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::string GetJString(JNIEnv* env, jstring jstr) { | ||||||
|  |     std::string result = ""; | ||||||
|  |     if (!jstr) | ||||||
|  |         return result; | ||||||
|  | 
 | ||||||
|  |     const char* s = env->GetStringUTFChars(jstr, nullptr); | ||||||
|  |     result = s; | ||||||
|  |     env->ReleaseStringUTFChars(jstr, s); | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  | } // namespace CitraJNI
 | ||||||
							
								
								
									
										16
									
								
								src/android/app/src/main/cpp/native_interface.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/android/app/src/main/cpp/native_interface.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | ||||||
|  | // Copyright 2019 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <string> | ||||||
|  | #include <jni.h> | ||||||
|  | 
 | ||||||
|  | namespace CitraJNI { | ||||||
|  | extern "C" { | ||||||
|  | jint JNI_OnLoad(JavaVM* vm, void* reserved); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::string GetJString(JNIEnv* env, jstring jstr); | ||||||
|  | } // namespace CitraJNI
 | ||||||
							
								
								
									
										31
									
								
								src/android/app/src/main/cpp/ui/main/main_activity.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/android/app/src/main/cpp/ui/main/main_activity.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,31 @@ | ||||||
|  | // Copyright 2019 Citra Emulator Project
 | ||||||
|  | // Licensed under GPLv2 or any later version
 | ||||||
|  | // Refer to the license.txt file included.
 | ||||||
|  | 
 | ||||||
|  | #include "common/common_paths.h" | ||||||
|  | #include "common/file_util.h" | ||||||
|  | #include "common/logging/filter.h" | ||||||
|  | #include "common/logging/log.h" | ||||||
|  | #include "core/settings.h" | ||||||
|  | #include "logging/logcat_backend.h" | ||||||
|  | #include "native_interface.h" | ||||||
|  | 
 | ||||||
|  | namespace MainActivity { | ||||||
|  | extern "C" { | ||||||
|  | JNICALL void Java_org_citra_1emu_citra_ui_main_MainActivity_initUserPath(JNIEnv* env, jclass type, | ||||||
|  |                                                                          jstring path) { | ||||||
|  |     FileUtil::SetUserPath(CitraJNI::GetJString(env, path) + '/'); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | JNICALL void Java_org_citra_1emu_citra_ui_main_MainActivity_initLogging(JNIEnv* env, jclass type) { | ||||||
|  |     Log::Filter log_filter(Log::Level::Debug); | ||||||
|  |     log_filter.ParseFilterString(Settings::values.log_filter); | ||||||
|  |     Log::SetGlobalFilter(log_filter); | ||||||
|  | 
 | ||||||
|  |     const std::string& log_dir = FileUtil::GetUserPath(FileUtil::UserPath::LogDir); | ||||||
|  |     FileUtil::CreateFullPath(log_dir); | ||||||
|  |     Log::AddBackend(std::make_unique<Log::FileBackend>(log_dir + LOG_FILE)); | ||||||
|  |     Log::AddBackend(std::make_unique<Log::LogcatBackend>()); | ||||||
|  | } | ||||||
|  | }; | ||||||
|  | }; // namespace MainActivity
 | ||||||
|  | @ -6,4 +6,8 @@ package org.citra_emu.citra; | ||||||
| 
 | 
 | ||||||
| import android.app.Application; | import android.app.Application; | ||||||
| 
 | 
 | ||||||
| public class CitraApplication extends Application {} | public class CitraApplication extends Application { | ||||||
|  |     static { | ||||||
|  |         System.loadLibrary("citra-android"); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										41
									
								
								src/android/app/src/main/java/org/citra_emu/citra/LOG.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/android/app/src/main/java/org/citra_emu/citra/LOG.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | ||||||
|  | package org.citra_emu.citra; | ||||||
|  | 
 | ||||||
|  | public class LOG { | ||||||
|  | 
 | ||||||
|  |     private interface LOG_LEVEL { | ||||||
|  |         int TRACE = 0, DEBUG = 1, INFO = 2, WARNING = 3, ERROR = 4, CRITICAL = 5; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static void TRACE(String msg, Object... args) { | ||||||
|  |         LOG(LOG_LEVEL.TRACE, msg, args); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static void DEBUG(String msg, Object... args) { | ||||||
|  |         LOG(LOG_LEVEL.DEBUG, msg, args); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static void INFO(String msg, Object... args) { | ||||||
|  |         LOG(LOG_LEVEL.INFO, msg, args); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static void WARNING(String msg, Object... args) { | ||||||
|  |         LOG(LOG_LEVEL.WARNING, msg, args); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static void ERROR(String msg, Object... args) { | ||||||
|  |         LOG(LOG_LEVEL.ERROR, msg, args); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     public static void CRITICAL(String msg, Object... args) { | ||||||
|  |         LOG(LOG_LEVEL.CRITICAL, msg, args); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private static void LOG(int level, String msg, Object... args) { | ||||||
|  |         StackTraceElement trace = Thread.currentThread().getStackTrace()[4]; | ||||||
|  |         logEntry(level, trace.getFileName(), trace.getLineNumber(), trace.getMethodName(), | ||||||
|  |                  String.format(msg, args)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private static native void logEntry(int level, String file_name, int line_number, | ||||||
|  |                                         String function, String message); | ||||||
|  | } | ||||||
|  | @ -4,15 +4,55 @@ | ||||||
| 
 | 
 | ||||||
| package org.citra_emu.citra.ui.main; | package org.citra_emu.citra.ui.main; | ||||||
| 
 | 
 | ||||||
|  | import android.Manifest; | ||||||
|  | import android.content.pm.PackageManager; | ||||||
| import android.os.Bundle; | import android.os.Bundle; | ||||||
|  | import android.support.annotation.NonNull; | ||||||
|  | import android.support.v7.app.AlertDialog; | ||||||
| import android.support.v7.app.AppCompatActivity; | import android.support.v7.app.AppCompatActivity; | ||||||
| 
 | 
 | ||||||
| import org.citra_emu.citra.R; | import org.citra_emu.citra.R; | ||||||
|  | import org.citra_emu.citra.utils.FileUtil; | ||||||
|  | import org.citra_emu.citra.utils.PermissionUtil; | ||||||
| 
 | 
 | ||||||
| public final class MainActivity extends AppCompatActivity { | public final class MainActivity extends AppCompatActivity { | ||||||
|  | 
 | ||||||
|  |     // Java enums suck | ||||||
|  |     private interface PermissionCodes { int INITIALIZE = 0; } | ||||||
|  | 
 | ||||||
|     @Override |     @Override | ||||||
|     protected void onCreate(Bundle savedInstanceState) { |     protected void onCreate(Bundle savedInstanceState) { | ||||||
|         super.onCreate(savedInstanceState); |         super.onCreate(savedInstanceState); | ||||||
|         setContentView(R.layout.activity_main); |         setContentView(R.layout.activity_main); | ||||||
|  | 
 | ||||||
|  |         PermissionUtil.verifyPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE, | ||||||
|  |                                         PermissionCodes.INITIALIZE); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     @Override | ||||||
|  |     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, | ||||||
|  |                                            @NonNull int[] grantResults) { | ||||||
|  |         switch (requestCode) { | ||||||
|  |         case PermissionCodes.INITIALIZE: | ||||||
|  |             if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { | ||||||
|  |                 initUserPath(FileUtil.getUserPath().toString()); | ||||||
|  |                 initLogging(); | ||||||
|  |             } else { | ||||||
|  |                 AlertDialog.Builder dialog = | ||||||
|  |                     new AlertDialog.Builder(this) | ||||||
|  |                         .setTitle("Permission Error") | ||||||
|  |                         .setMessage("Citra requires storage permissions to function.") | ||||||
|  |                         .setCancelable(false) | ||||||
|  |                         .setPositiveButton("OK", (dialogInterface, which) -> { | ||||||
|  |                             PermissionUtil.verifyPermission( | ||||||
|  |                                 MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE, | ||||||
|  |                                 PermissionCodes.INITIALIZE); | ||||||
|  |                         }); | ||||||
|  |                 dialog.show(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private static native void initUserPath(String path); | ||||||
|  |     private static native void initLogging(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -0,0 +1,19 @@ | ||||||
|  | // Copyright 2019 Citra Emulator Project | ||||||
|  | // Licensed under GPLv2 or any later version | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  | 
 | ||||||
|  | package org.citra_emu.citra.utils; | ||||||
|  | 
 | ||||||
|  | import android.os.Environment; | ||||||
|  | 
 | ||||||
|  | import java.io.File; | ||||||
|  | 
 | ||||||
|  | public class FileUtil { | ||||||
|  |     public static File getUserPath() { | ||||||
|  |         File storage = Environment.getExternalStorageDirectory(); | ||||||
|  |         File userPath = new File(storage, "citra"); | ||||||
|  |         if (!userPath.isDirectory()) | ||||||
|  |             userPath.mkdir(); | ||||||
|  |         return userPath; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,32 @@ | ||||||
|  | // Copyright 2019 Citra Emulator Project | ||||||
|  | // Licensed under GPLv2 or any later version | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  | 
 | ||||||
|  | package org.citra_emu.citra.utils; | ||||||
|  | 
 | ||||||
|  | import android.app.Activity; | ||||||
|  | import android.content.pm.PackageManager; | ||||||
|  | import android.support.v4.app.ActivityCompat; | ||||||
|  | import android.support.v4.content.ContextCompat; | ||||||
|  | 
 | ||||||
|  | public class PermissionUtil { | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Checks a permission, if needed shows a dialog to request it | ||||||
|  |      * | ||||||
|  |      * @param activity    the activity requiring the permission | ||||||
|  |      * @param permission  the permission needed | ||||||
|  |      * @param requestCode supplied to the callback to determine the next action | ||||||
|  |      */ | ||||||
|  |     public static void verifyPermission(Activity activity, String permission, int requestCode) { | ||||||
|  |         if (ContextCompat.checkSelfPermission(activity, permission) == | ||||||
|  |             PackageManager.PERMISSION_GRANTED) { | ||||||
|  |             // call the callback called by requestPermissions | ||||||
|  |             activity.onRequestPermissionsResult(requestCode, new String[] {permission}, | ||||||
|  |                                                 new int[] {PackageManager.PERMISSION_GRANTED}); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         ActivityCompat.requestPermissions(activity, new String[] {permission}, requestCode); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -543,11 +543,12 @@ std::string GetCurrentDir() { | ||||||
| // Get the current working directory (getcwd uses malloc)
 | // Get the current working directory (getcwd uses malloc)
 | ||||||
| #ifdef _WIN32 | #ifdef _WIN32 | ||||||
|     wchar_t* dir; |     wchar_t* dir; | ||||||
|     if (!(dir = _wgetcwd(nullptr, 0))) { |     if (!(dir = _wgetcwd(nullptr, 0))) | ||||||
| #else | #else | ||||||
|     char* dir; |     char* dir; | ||||||
|     if (!(dir = getcwd(nullptr, 0))) { |     if (!(dir = getcwd(nullptr, 0))) | ||||||
| #endif | #endif | ||||||
|  |     { | ||||||
|         LOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: {}", GetLastErrorMsg()); |         LOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: {}", GetLastErrorMsg()); | ||||||
|         return nullptr; |         return nullptr; | ||||||
|     } |     } | ||||||
|  | @ -695,6 +696,8 @@ void SetUserPath(const std::string& path) { | ||||||
| 
 | 
 | ||||||
|         g_paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP); |         g_paths.emplace(UserPath::ConfigDir, user_path + CONFIG_DIR DIR_SEP); | ||||||
|         g_paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP); |         g_paths.emplace(UserPath::CacheDir, user_path + CACHE_DIR DIR_SEP); | ||||||
|  | #elif ANDROID | ||||||
|  |         ASSERT_MSG(false, "Specified path {} is not valid", path); | ||||||
| #else | #else | ||||||
|         if (FileUtil::Exists(ROOT_DIR DIR_SEP USERDATA_DIR)) { |         if (FileUtil::Exists(ROOT_DIR DIR_SEP USERDATA_DIR)) { | ||||||
|             user_path = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP; |             user_path = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP; | ||||||
|  |  | ||||||
|  | @ -8,6 +8,7 @@ | ||||||
| #include <condition_variable> | #include <condition_variable> | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <mutex> | #include <mutex> | ||||||
|  | #include <regex> | ||||||
| #include <thread> | #include <thread> | ||||||
| #include <vector> | #include <vector> | ||||||
| #ifdef _WIN32 | #ifdef _WIN32 | ||||||
|  | @ -253,13 +254,15 @@ Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsign | ||||||
|     using std::chrono::duration_cast; |     using std::chrono::duration_cast; | ||||||
|     using std::chrono::steady_clock; |     using std::chrono::steady_clock; | ||||||
| 
 | 
 | ||||||
|  |     // matches from the beginning up to the last '../' or 'src/'
 | ||||||
|  |     static const std::regex trim_source_path(R"(.*([\/\\]|^)((\.\.)|(src))[\/\\])"); | ||||||
|     static steady_clock::time_point time_origin = steady_clock::now(); |     static steady_clock::time_point time_origin = steady_clock::now(); | ||||||
| 
 | 
 | ||||||
|     Entry entry; |     Entry entry; | ||||||
|     entry.timestamp = duration_cast<std::chrono::microseconds>(steady_clock::now() - time_origin); |     entry.timestamp = duration_cast<std::chrono::microseconds>(steady_clock::now() - time_origin); | ||||||
|     entry.log_class = log_class; |     entry.log_class = log_class; | ||||||
|     entry.log_level = log_level; |     entry.log_level = log_level; | ||||||
|     entry.filename = Common::TrimSourcePath(filename); |     entry.filename = std::regex_replace(filename, trim_source_path, ""); | ||||||
|     entry.line_num = line_nr; |     entry.line_num = line_nr; | ||||||
|     entry.function = function; |     entry.function = function; | ||||||
|     entry.message = std::move(message); |     entry.message = std::move(message); | ||||||
|  |  | ||||||
|  | @ -209,26 +209,4 @@ std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, std::size_t | ||||||
| 
 | 
 | ||||||
|     return std::string(buffer, len); |     return std::string(buffer, len); | ||||||
| } | } | ||||||
| 
 |  | ||||||
| const char* TrimSourcePath(const char* path, const char* root) { |  | ||||||
|     const char* p = path; |  | ||||||
| 
 |  | ||||||
|     while (*p != '\0') { |  | ||||||
|         const char* next_slash = p; |  | ||||||
|         while (*next_slash != '\0' && *next_slash != '/' && *next_slash != '\\') { |  | ||||||
|             ++next_slash; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         bool is_src = Common::ComparePartialString(p, next_slash, root); |  | ||||||
|         p = next_slash; |  | ||||||
| 
 |  | ||||||
|         if (*p != '\0') { |  | ||||||
|             ++p; |  | ||||||
|         } |  | ||||||
|         if (is_src) { |  | ||||||
|             path = p; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     return path; |  | ||||||
| } |  | ||||||
| } // namespace Common
 | } // namespace Common
 | ||||||
|  |  | ||||||
|  | @ -64,16 +64,4 @@ bool ComparePartialString(InIt begin, InIt end, const char* other) { | ||||||
|  */ |  */ | ||||||
| std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, std::size_t max_len); | std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, std::size_t max_len); | ||||||
| 
 | 
 | ||||||
| /**
 |  | ||||||
|  * Attempts to trim an arbitrary prefix from `path`, leaving only the part starting at `root`. It's |  | ||||||
|  * intended to be used to strip a system-specific build directory from the `__FILE__` macro, |  | ||||||
|  * leaving only the path relative to the sources root. |  | ||||||
|  * |  | ||||||
|  * @param path The input file path as a null-terminated string |  | ||||||
|  * @param root The name of the root source directory as a null-terminated string. Path up to and |  | ||||||
|  *             including the last occurrence of this name will be stripped |  | ||||||
|  * @return A pointer to the same string passed as `path`, but starting at the trimmed portion |  | ||||||
|  */ |  | ||||||
| const char* TrimSourcePath(const char* path, const char* root = "src"); |  | ||||||
| 
 |  | ||||||
| } // namespace Common
 | } // namespace Common
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue