Merge pull request #4575 from BreadFish64/android6
android: add logging
This commit is contained in:
commit
fd7730e7c8
@ -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…
Reference in New Issue
Block a user