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 | ||||
| TabWidth:        4 | ||||
| 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) | ||||
| 
 | ||||
| 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_library(log-lib log) | ||||
| 
 | ||||
| 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; | ||||
| 
 | ||||
| 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; | ||||
| 
 | ||||
| import android.Manifest; | ||||
| import android.content.pm.PackageManager; | ||||
| import android.os.Bundle; | ||||
| import android.support.annotation.NonNull; | ||||
| import android.support.v7.app.AlertDialog; | ||||
| import android.support.v7.app.AppCompatActivity; | ||||
| 
 | ||||
| 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 { | ||||
| 
 | ||||
|     // Java enums suck | ||||
|     private interface PermissionCodes { int INITIALIZE = 0; } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onCreate(Bundle savedInstanceState) { | ||||
|         super.onCreate(savedInstanceState); | ||||
|         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)
 | ||||
| #ifdef _WIN32 | ||||
|     wchar_t* dir; | ||||
|     if (!(dir = _wgetcwd(nullptr, 0))) { | ||||
|     if (!(dir = _wgetcwd(nullptr, 0))) | ||||
| #else | ||||
|     char* dir; | ||||
|     if (!(dir = getcwd(nullptr, 0))) { | ||||
|     if (!(dir = getcwd(nullptr, 0))) | ||||
| #endif | ||||
|     { | ||||
|         LOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: {}", GetLastErrorMsg()); | ||||
|         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::CacheDir, user_path + CACHE_DIR DIR_SEP); | ||||
| #elif ANDROID | ||||
|         ASSERT_MSG(false, "Specified path {} is not valid", path); | ||||
| #else | ||||
|         if (FileUtil::Exists(ROOT_DIR DIR_SEP USERDATA_DIR)) { | ||||
|             user_path = ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP; | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ | |||
| #include <condition_variable> | ||||
| #include <memory> | ||||
| #include <mutex> | ||||
| #include <regex> | ||||
| #include <thread> | ||||
| #include <vector> | ||||
| #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::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(); | ||||
| 
 | ||||
|     Entry entry; | ||||
|     entry.timestamp = duration_cast<std::chrono::microseconds>(steady_clock::now() - time_origin); | ||||
|     entry.log_class = log_class; | ||||
|     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.function = function; | ||||
|     entry.message = std::move(message); | ||||
|  |  | |||
|  | @ -209,26 +209,4 @@ std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, std::size_t | |||
| 
 | ||||
|     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
 | ||||
|  |  | |||
|  | @ -64,16 +64,4 @@ bool ComparePartialString(InIt begin, InIt end, const char* other) { | |||
|  */ | ||||
| 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
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue