1 // Copyright 2023 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef JNI_ZERO_LOGGING_H_
6 #define JNI_ZERO_LOGGING_H_
7
8 #include "third_party/jni_zero/jni_export.h"
9
10 // Simplified version of Google's logging. Adapted from perfetto's
11 // implementation.
12 namespace jni_zero {
13
14 // Constexpr functions to extract basename(__FILE__), e.g.: ../foo/f.c -> f.c .
StrEnd(const char * s)15 constexpr const char* StrEnd(const char* s) {
16 return *s ? StrEnd(s + 1) : s;
17 }
18
BasenameRecursive(const char * s,const char * begin,const char * end)19 constexpr const char* BasenameRecursive(const char* s,
20 const char* begin,
21 const char* end) {
22 return (*s == '/' && s < end)
23 ? (s + 1)
24 : ((s > begin) ? BasenameRecursive(s - 1, begin, end) : s);
25 }
26
Basename(const char * str)27 constexpr const char* Basename(const char* str) {
28 return BasenameRecursive(StrEnd(str), str, StrEnd(str));
29 }
30
31 enum LogLev { kLogInfo = 0, kLogError, kLogFatal };
32
33 struct LogMessageCallbackArgs {
34 LogLev level;
35 int line;
36 const char* filename;
37 const char* message;
38 };
39
40 using LogMessageCallback = void (*)(LogMessageCallbackArgs);
41
42 // This is not thread safe and must be called before using tracing from other
43 // threads.
44 JNI_ZERO_COMPONENT_BUILD_EXPORT void SetLogMessageCallback(
45 LogMessageCallback callback);
46
47 JNI_ZERO_COMPONENT_BUILD_EXPORT void LogMessage(LogLev,
48 const char* fname,
49 int line,
50 const char* fmt,
51 ...)
52 __attribute__((__format__(__printf__, 4, 5)));
53
54 #define JNI_ZERO_IMMEDIATE_CRASH() \
55 do { \
56 __builtin_trap(); \
57 __builtin_unreachable(); \
58 } while (0)
59 #define JNI_ZERO_XLOG(level, fmt, ...) \
60 ::jni_zero::LogMessage(level, ::jni_zero::Basename(__FILE__), __LINE__, fmt, \
61 ##__VA_ARGS__)
62 #define JNI_ZERO_ILOG(fmt, ...) \
63 JNI_ZERO_XLOG(::jni_zero::kLogInfo, fmt, ##__VA_ARGS__)
64 #define JNI_ZERO_ELOG(fmt, ...) \
65 JNI_ZERO_XLOG(::jni_zero::kLogError, fmt, ##__VA_ARGS__)
66 #define JNI_ZERO_FLOG(fmt, ...) \
67 JNI_ZERO_XLOG(::jni_zero::kLogFatal, fmt, ##__VA_ARGS__)
68
69 #define JNI_ZERO_CHECK(x) \
70 do { \
71 if (__builtin_expect(!(x), 0)) { \
72 JNI_ZERO_FLOG("%s", "JNI_ZERO_CHECK(" #x ")"); \
73 } \
74 } while (0)
75 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
76 #define JNI_ZERO_DCHECK(x) \
77 do { \
78 } while (false && (x))
79 #else
80 #define JNI_ZERO_DCHECK(x) JNI_ZERO_CHECK(x)
81 #endif
82 } // namespace jni_zero
83
84 #endif // JNI_ZERO_LOGGING_H_
85