From 28b2ee9cd72b278795c283101dd7df86c9d9368c Mon Sep 17 00:00:00 2001 From: BreadFish64 Date: Thu, 17 Jan 2019 17:03:15 -0600 Subject: [PATCH 1/5] add java to .clang-format --- src/.clang-format | 84 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/src/.clang-format b/src/.clang-format index 1c6b71b2e..bf8872643 100644 --- a/src/.clang-format +++ b/src/.clang-format @@ -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 ... From 9848610ea26369e65e0db13b6d7d9d2de093cde7 Mon Sep 17 00:00:00 2001 From: BreadFish64 Date: Tue, 15 Jan 2019 19:12:43 -0600 Subject: [PATCH 2/5] android: init user path --- src/android/app/src/main/cpp/CMakeLists.txt | 5 ++- src/android/app/src/main/cpp/dummy.cpp | 3 -- .../app/src/main/cpp/native_interface.cpp | 22 +++++++++++ .../app/src/main/cpp/native_interface.h | 16 ++++++++ .../src/main/cpp/ui/main/main_activity.cpp | 15 ++++++++ .../org/citra_emu/citra/CitraApplication.java | 6 ++- .../citra_emu/citra/ui/main/MainActivity.java | 38 +++++++++++++++++++ .../org/citra_emu/citra/utils/FileUtil.java | 19 ++++++++++ .../citra_emu/citra/utils/PermissionUtil.java | 32 ++++++++++++++++ src/common/file_util.cpp | 2 + 10 files changed, 153 insertions(+), 5 deletions(-) delete mode 100644 src/android/app/src/main/cpp/dummy.cpp create mode 100644 src/android/app/src/main/cpp/native_interface.cpp create mode 100644 src/android/app/src/main/cpp/native_interface.h create mode 100644 src/android/app/src/main/cpp/ui/main/main_activity.cpp create mode 100644 src/android/app/src/main/java/org/citra_emu/citra/utils/FileUtil.java create mode 100644 src/android/app/src/main/java/org/citra_emu/citra/utils/PermissionUtil.java diff --git a/src/android/app/src/main/cpp/CMakeLists.txt b/src/android/app/src/main/cpp/CMakeLists.txt index 674b9287c..08db8f4c7 100644 --- a/src/android/app/src/main/cpp/CMakeLists.txt +++ b/src/android/app/src/main/cpp/CMakeLists.txt @@ -1,10 +1,13 @@ cmake_minimum_required(VERSION 3.8) add_library(citra-android SHARED - dummy.cpp + 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 "../../../../../" "./") diff --git a/src/android/app/src/main/cpp/dummy.cpp b/src/android/app/src/main/cpp/dummy.cpp deleted file mode 100644 index d0ef94a09..000000000 --- a/src/android/app/src/main/cpp/dummy.cpp +++ /dev/null @@ -1,3 +0,0 @@ -int dummy(int a, int b) { - return a + b; -} diff --git a/src/android/app/src/main/cpp/native_interface.cpp b/src/android/app/src/main/cpp/native_interface.cpp new file mode 100644 index 000000000..fc4d73b77 --- /dev/null +++ b/src/android/app/src/main/cpp/native_interface.cpp @@ -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 diff --git a/src/android/app/src/main/cpp/native_interface.h b/src/android/app/src/main/cpp/native_interface.h new file mode 100644 index 000000000..a7b99cb51 --- /dev/null +++ b/src/android/app/src/main/cpp/native_interface.h @@ -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 +#include + +namespace CitraJNI { +extern "C" { +jint JNI_OnLoad(JavaVM* vm, void* reserved); +} + +std::string GetJString(JNIEnv* env, jstring jstr); +} // namespace CitraJNI diff --git a/src/android/app/src/main/cpp/ui/main/main_activity.cpp b/src/android/app/src/main/cpp/ui/main/main_activity.cpp new file mode 100644 index 000000000..412c358a0 --- /dev/null +++ b/src/android/app/src/main/cpp/ui/main/main_activity.cpp @@ -0,0 +1,15 @@ +// Copyright 2019 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/file_util.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)); +} +}; +}; // namespace MainActivity diff --git a/src/android/app/src/main/java/org/citra_emu/citra/CitraApplication.java b/src/android/app/src/main/java/org/citra_emu/citra/CitraApplication.java index 07a782853..10cb52783 100644 --- a/src/android/app/src/main/java/org/citra_emu/citra/CitraApplication.java +++ b/src/android/app/src/main/java/org/citra_emu/citra/CitraApplication.java @@ -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"); + } +} diff --git a/src/android/app/src/main/java/org/citra_emu/citra/ui/main/MainActivity.java b/src/android/app/src/main/java/org/citra_emu/citra/ui/main/MainActivity.java index 97b36f0c1..0ae764798 100644 --- a/src/android/app/src/main/java/org/citra_emu/citra/ui/main/MainActivity.java +++ b/src/android/app/src/main/java/org/citra_emu/citra/ui/main/MainActivity.java @@ -4,15 +4,53 @@ 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 INIT_USER_PATH = 0; } + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); + + PermissionUtil.verifyPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE, + PermissionCodes.INIT_USER_PATH); } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, + @NonNull int[] grantResults) { + switch (requestCode) { + case PermissionCodes.INIT_USER_PATH: + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { + initUserPath(FileUtil.getUserPath().toString()); + } 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.INIT_USER_PATH); + }); + dialog.show(); + } + } + } + + private static native void initUserPath(String path); } diff --git a/src/android/app/src/main/java/org/citra_emu/citra/utils/FileUtil.java b/src/android/app/src/main/java/org/citra_emu/citra/utils/FileUtil.java new file mode 100644 index 000000000..5346c5352 --- /dev/null +++ b/src/android/app/src/main/java/org/citra_emu/citra/utils/FileUtil.java @@ -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; + } +} diff --git a/src/android/app/src/main/java/org/citra_emu/citra/utils/PermissionUtil.java b/src/android/app/src/main/java/org/citra_emu/citra/utils/PermissionUtil.java new file mode 100644 index 000000000..33c8129e5 --- /dev/null +++ b/src/android/app/src/main/java/org/citra_emu/citra/utils/PermissionUtil.java @@ -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); + } +} diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index 52288847a..e5f8eb899 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp @@ -695,6 +695,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; From f767b5fdef0be77b62b37f678ec76e931bc4a7ef Mon Sep 17 00:00:00 2001 From: BreadFish64 Date: Fri, 15 Feb 2019 20:37:36 -0600 Subject: [PATCH 3/5] android: add logging --- src/android/app/src/main/cpp/CMakeLists.txt | 3 ++ src/android/app/src/main/cpp/logging/log.cpp | 15 +++++++ .../src/main/cpp/logging/logcat_backend.cpp | 38 +++++++++++++++++ .../app/src/main/cpp/logging/logcat_backend.h | 22 ++++++++++ .../src/main/cpp/ui/main/main_activity.cpp | 18 +++++++- .../main/java/org/citra_emu/citra/LOG.java | 41 +++++++++++++++++++ .../citra_emu/citra/ui/main/MainActivity.java | 10 +++-- src/common/logging/backend.cpp | 2 +- src/common/string_util.cpp | 31 ++++++-------- src/common/string_util.h | 10 ++--- 10 files changed, 160 insertions(+), 30 deletions(-) create mode 100644 src/android/app/src/main/cpp/logging/log.cpp create mode 100644 src/android/app/src/main/cpp/logging/logcat_backend.cpp create mode 100644 src/android/app/src/main/cpp/logging/logcat_backend.h create mode 100644 src/android/app/src/main/java/org/citra_emu/citra/LOG.java diff --git a/src/android/app/src/main/cpp/CMakeLists.txt b/src/android/app/src/main/cpp/CMakeLists.txt index 08db8f4c7..f3a7e0131 100644 --- a/src/android/app/src/main/cpp/CMakeLists.txt +++ b/src/android/app/src/main/cpp/CMakeLists.txt @@ -1,6 +1,9 @@ cmake_minimum_required(VERSION 3.8) add_library(citra-android SHARED + logging/log.cpp + logging/logcat_backend.cpp + logging/logcat_backend.h native_interface.cpp native_interface.h ui/main/main_activity.cpp diff --git a/src/android/app/src/main/cpp/logging/log.cpp b/src/android/app/src/main/cpp/logging/log.cpp new file mode 100644 index 000000000..044f4eb4c --- /dev/null +++ b/src/android/app/src/main/cpp/logging/log.cpp @@ -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), GetJString(env, file_name).data(), + static_cast(line_number), GetJString(env, function).data(), + GetJString(env, msg).data()); +} +} +} // namespace Log diff --git a/src/android/app/src/main/cpp/logging/logcat_backend.cpp b/src/android/app/src/main/cpp/logging/logcat_backend.cpp new file mode 100644 index 000000000..17b6ae1a0 --- /dev/null +++ b/src/android/app/src/main/cpp/logging/logcat_backend.cpp @@ -0,0 +1,38 @@ +// Copyright 2019 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#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 \ No newline at end of file diff --git a/src/android/app/src/main/cpp/logging/logcat_backend.h b/src/android/app/src/main/cpp/logging/logcat_backend.h new file mode 100644 index 000000000..f3bac4762 --- /dev/null +++ b/src/android/app/src/main/cpp/logging/logcat_backend.h @@ -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 diff --git a/src/android/app/src/main/cpp/ui/main/main_activity.cpp b/src/android/app/src/main/cpp/ui/main/main_activity.cpp index 412c358a0..b99ba1890 100644 --- a/src/android/app/src/main/cpp/ui/main/main_activity.cpp +++ b/src/android/app/src/main/cpp/ui/main/main_activity.cpp @@ -2,14 +2,30 @@ // 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)); + 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_dir + LOG_FILE)); + Log::AddBackend(std::make_unique()); } }; }; // namespace MainActivity diff --git a/src/android/app/src/main/java/org/citra_emu/citra/LOG.java b/src/android/app/src/main/java/org/citra_emu/citra/LOG.java new file mode 100644 index 000000000..c52f30b68 --- /dev/null +++ b/src/android/app/src/main/java/org/citra_emu/citra/LOG.java @@ -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); +} diff --git a/src/android/app/src/main/java/org/citra_emu/citra/ui/main/MainActivity.java b/src/android/app/src/main/java/org/citra_emu/citra/ui/main/MainActivity.java index 0ae764798..5b4f3d3bc 100644 --- a/src/android/app/src/main/java/org/citra_emu/citra/ui/main/MainActivity.java +++ b/src/android/app/src/main/java/org/citra_emu/citra/ui/main/MainActivity.java @@ -18,7 +18,7 @@ import org.citra_emu.citra.utils.PermissionUtil; public final class MainActivity extends AppCompatActivity { // Java enums suck - private interface PermissionCodes { int INIT_USER_PATH = 0; } + private interface PermissionCodes { int INITIALIZE = 0; } @Override protected void onCreate(Bundle savedInstanceState) { @@ -26,16 +26,17 @@ public final class MainActivity extends AppCompatActivity { setContentView(R.layout.activity_main); PermissionUtil.verifyPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE, - PermissionCodes.INIT_USER_PATH); + PermissionCodes.INITIALIZE); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode) { - case PermissionCodes.INIT_USER_PATH: + case PermissionCodes.INITIALIZE: if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { initUserPath(FileUtil.getUserPath().toString()); + initLogging(); } else { AlertDialog.Builder dialog = new AlertDialog.Builder(this) @@ -45,7 +46,7 @@ public final class MainActivity extends AppCompatActivity { .setPositiveButton("OK", (dialogInterface, which) -> { PermissionUtil.verifyPermission( MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE, - PermissionCodes.INIT_USER_PATH); + PermissionCodes.INITIALIZE); }); dialog.show(); } @@ -53,4 +54,5 @@ public final class MainActivity extends AppCompatActivity { } private static native void initUserPath(String path); + private static native void initLogging(); } diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index d93c5bbd7..f0062779b 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -259,7 +259,7 @@ Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsign entry.timestamp = duration_cast(steady_clock::now() - time_origin); entry.log_class = log_class; entry.log_level = log_level; - entry.filename = Common::TrimSourcePath(filename); + entry.filename = Common::TrimSourcePath(filename, {R"(\.\.)", "src"}).data(); entry.line_num = line_nr; entry.function = function; entry.message = std::move(message); diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 541a2bf4e..9306c8bed 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "common/common_paths.h" #include "common/logging/log.h" @@ -210,25 +211,17 @@ 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; - } +std::string TrimSourcePath(const std::string& file_path, const std::vector& roots) { + // match from beginning of path to dir sep + std::string regex_src = R"(.*([\/\\]|^)()"; + // plus the last occurrence of any root + for (auto root = roots.begin(); root < roots.end() - 1; ++root) { + regex_src += '(' + *root + ")|"; } - return path; + regex_src += '(' + roots.back() + ')'; + // plus dir sep + regex_src += R"()[\/\\])"; + std::regex regex(regex_src); + return std::regex_replace(file_path, regex, ""); } } // namespace Common diff --git a/src/common/string_util.h b/src/common/string_util.h index d8fa4053e..aa0d147a4 100644 --- a/src/common/string_util.h +++ b/src/common/string_util.h @@ -69,11 +69,11 @@ std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, std::size_t * 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 + * @param path The input file path as a string + * @param roots The name of the root source directorys as a vector of strings. Path up to and + * including the last occurrence of these names will be stripped + * @return The trimmed path as a string */ -const char* TrimSourcePath(const char* path, const char* root = "src"); +std::string TrimSourcePath(const std::string& file_path, const std::vector& roots); } // namespace Common From 605dfe80e7261cd2ee213cff8179eab597acb169 Mon Sep 17 00:00:00 2001 From: BreadFish64 Date: Sat, 9 Mar 2019 19:15:35 -0600 Subject: [PATCH 4/5] appease clang format --- src/common/file_util.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index e5f8eb899..62a9a5b95 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp @@ -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; } From 36e368ff9928d20b42ef3a53a0472af577f8554b Mon Sep 17 00:00:00 2001 From: BreadFish64 Date: Sun, 10 Mar 2019 19:18:09 -0500 Subject: [PATCH 5/5] remove Common::TrimSourcePath MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wwylele / 白疾風Today at 6:14 PM I doubt the performance of constructing regex everytime the function is called Is TrimSourcePath only called by logging? if so, you can move the implementation into logging, and cache the regex object into global This function is probably too specific to be in common anyway --- src/common/logging/backend.cpp | 5 ++++- src/common/string_util.cpp | 15 --------------- src/common/string_util.h | 12 ------------ 3 files changed, 4 insertions(+), 28 deletions(-) diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index f0062779b..d440d910a 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #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(steady_clock::now() - time_origin); entry.log_class = log_class; entry.log_level = log_level; - entry.filename = Common::TrimSourcePath(filename, {R"(\.\.)", "src"}).data(); + entry.filename = std::regex_replace(filename, trim_source_path, ""); entry.line_num = line_nr; entry.function = function; entry.message = std::move(message); diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 9306c8bed..f3c64884a 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include "common/common_paths.h" #include "common/logging/log.h" @@ -210,18 +209,4 @@ std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, std::size_t return std::string(buffer, len); } - -std::string TrimSourcePath(const std::string& file_path, const std::vector& roots) { - // match from beginning of path to dir sep - std::string regex_src = R"(.*([\/\\]|^)()"; - // plus the last occurrence of any root - for (auto root = roots.begin(); root < roots.end() - 1; ++root) { - regex_src += '(' + *root + ")|"; - } - regex_src += '(' + roots.back() + ')'; - // plus dir sep - regex_src += R"()[\/\\])"; - std::regex regex(regex_src); - return std::regex_replace(file_path, regex, ""); -} } // namespace Common diff --git a/src/common/string_util.h b/src/common/string_util.h index aa0d147a4..110715dce 100644 --- a/src/common/string_util.h +++ b/src/common/string_util.h @@ -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 string - * @param roots The name of the root source directorys as a vector of strings. Path up to and - * including the last occurrence of these names will be stripped - * @return The trimmed path as a string - */ -std::string TrimSourcePath(const std::string& file_path, const std::vector& roots); - } // namespace Common