SDL: Added SDL_LogTrace()

From 231ea07617d8719679df87481ca4406b147539c1 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Tue, 17 Sep 2024 01:55:22 -0700
Subject: [PATCH] Added SDL_LogTrace()

---
 include/SDL3/SDL_log.h            | 34 +++++++++++++++++++++++++++++++
 src/SDL_log.c                     | 22 +++++++++++++++-----
 src/dynapi/SDL_dynapi.c           |  2 ++
 src/dynapi/SDL_dynapi.sym         |  1 +
 src/dynapi/SDL_dynapi_overrides.h |  1 +
 src/dynapi/SDL_dynapi_procs.h     |  1 +
 test/testautomation_log.c         |  4 ++--
 7 files changed, 58 insertions(+), 7 deletions(-)

diff --git a/include/SDL3/SDL_log.h b/include/SDL3/SDL_log.h
index 356ce2b0c7ef0..f2891c8bdfd9e 100644
--- a/include/SDL3/SDL_log.h
+++ b/include/SDL3/SDL_log.h
@@ -121,6 +121,7 @@ typedef enum SDL_LogCategory
 typedef enum SDL_LogPriority
 {
     SDL_LOG_PRIORITY_INVALID,
+    SDL_LOG_PRIORITY_TRACE,
     SDL_LOG_PRIORITY_VERBOSE,
     SDL_LOG_PRIORITY_DEBUG,
     SDL_LOG_PRIORITY_INFO,
@@ -228,11 +229,37 @@ extern SDL_DECLSPEC SDL_bool SDLCALL SDL_SetLogPriorityPrefix(SDL_LogPriority pr
  * \sa SDL_LogInfo
  * \sa SDL_LogMessage
  * \sa SDL_LogMessageV
+ * \sa SDL_LogTrace
  * \sa SDL_LogVerbose
  * \sa SDL_LogWarn
  */
 extern SDL_DECLSPEC void SDLCALL SDL_Log(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1);
 
+/**
+ * Log a message with SDL_LOG_PRIORITY_TRACE.
+ *
+ * \param category the category of the message.
+ * \param fmt a printf() style message format string.
+ * \param ... additional parameters matching % tokens in the **fmt** string,
+ *            if any.
+ *
+ * \threadsafety It is safe to call this function from any thread.
+ *
+ * \since This function is available since SDL 3.0.0.
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogCritical
+ * \sa SDL_LogDebug
+ * \sa SDL_LogError
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessage
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogTrace
+ * \sa SDL_LogVerbose
+ * \sa SDL_LogWarn
+ */
+extern SDL_DECLSPEC void SDLCALL SDL_LogTrace(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2);
+
 /**
  * Log a message with SDL_LOG_PRIORITY_VERBOSE.
  *
@@ -274,6 +301,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_LogVerbose(int category, SDL_PRINTF_FORMAT_
  * \sa SDL_LogInfo
  * \sa SDL_LogMessage
  * \sa SDL_LogMessageV
+ * \sa SDL_LogTrace
  * \sa SDL_LogVerbose
  * \sa SDL_LogWarn
  */
@@ -297,6 +325,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_LogDebug(int category, SDL_PRINTF_FORMAT_ST
  * \sa SDL_LogError
  * \sa SDL_LogMessage
  * \sa SDL_LogMessageV
+ * \sa SDL_LogTrace
  * \sa SDL_LogVerbose
  * \sa SDL_LogWarn
  */
@@ -321,6 +350,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_LogInfo(int category, SDL_PRINTF_FORMAT_STR
  * \sa SDL_LogInfo
  * \sa SDL_LogMessage
  * \sa SDL_LogMessageV
+ * \sa SDL_LogTrace
  * \sa SDL_LogVerbose
  */
 extern SDL_DECLSPEC void SDLCALL SDL_LogWarn(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2);
@@ -343,6 +373,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_LogWarn(int category, SDL_PRINTF_FORMAT_STR
  * \sa SDL_LogInfo
  * \sa SDL_LogMessage
  * \sa SDL_LogMessageV
+ * \sa SDL_LogTrace
  * \sa SDL_LogVerbose
  * \sa SDL_LogWarn
  */
@@ -366,6 +397,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_LogError(int category, SDL_PRINTF_FORMAT_ST
  * \sa SDL_LogInfo
  * \sa SDL_LogMessage
  * \sa SDL_LogMessageV
+ * \sa SDL_LogTrace
  * \sa SDL_LogVerbose
  * \sa SDL_LogWarn
  */
@@ -390,6 +422,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_LogCritical(int category, SDL_PRINTF_FORMAT
  * \sa SDL_LogError
  * \sa SDL_LogInfo
  * \sa SDL_LogMessageV
+ * \sa SDL_LogTrace
  * \sa SDL_LogVerbose
  * \sa SDL_LogWarn
  */
@@ -415,6 +448,7 @@ extern SDL_DECLSPEC void SDLCALL SDL_LogMessage(int category,
  * \sa SDL_LogError
  * \sa SDL_LogInfo
  * \sa SDL_LogMessage
+ * \sa SDL_LogTrace
  * \sa SDL_LogVerbose
  * \sa SDL_LogWarn
  */
diff --git a/src/SDL_log.c b/src/SDL_log.c
index dd274bfaff4ef..f4fc429e82a2a 100644
--- a/src/SDL_log.c
+++ b/src/SDL_log.c
@@ -75,6 +75,7 @@ static void *SDL_log_userdata SDL_GUARDED_BY(SDL_log_function_lock) = NULL;
 // If this list changes, update the documentation for SDL_HINT_LOGGING
 static const char * const SDL_priority_names[] = {
     NULL,
+    "TRACE",
     "VERBOSE",
     "DEBUG",
     "INFO",
@@ -107,15 +108,17 @@ SDL_COMPILE_TIME_ASSERT(category_names, SDL_arraysize(SDL_category_names) == SDL
 #endif
 
 #ifdef SDL_PLATFORM_ANDROID
-static int SDL_android_priority[SDL_LOG_PRIORITY_COUNT] = {
+static int SDL_android_priority[] = {
     ANDROID_LOG_UNKNOWN,
     ANDROID_LOG_VERBOSE,
+    ANDROID_LOG_VERBOSE,
     ANDROID_LOG_DEBUG,
     ANDROID_LOG_INFO,
     ANDROID_LOG_WARN,
     ANDROID_LOG_ERROR,
     ANDROID_LOG_FATAL
 };
+SDL_COMPILE_TIME_ASSERT(android_priority, SDL_arraysize(SDL_android_priority) == SDL_LOG_PRIORITY_COUNT);
 #endif // SDL_PLATFORM_ANDROID
 
 static void SDLCALL SDL_LoggingChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
@@ -302,7 +305,7 @@ static bool ParseLogPriority(const char *string, size_t length, SDL_LogPriority
             *priority = SDL_LOG_PRIORITY_COUNT;
             return true;
         }
-        if (i >= SDL_LOG_PRIORITY_VERBOSE && i < SDL_LOG_PRIORITY_COUNT) {
+        if (i > SDL_LOG_PRIORITY_INVALID && i < SDL_LOG_PRIORITY_COUNT) {
             *priority = (SDL_LogPriority)i;
             return true;
         }
@@ -314,7 +317,7 @@ static bool ParseLogPriority(const char *string, size_t length, SDL_LogPriority
         return true;
     }
 
-    for (i = SDL_LOG_PRIORITY_VERBOSE; i < SDL_LOG_PRIORITY_COUNT; ++i) {
+    for (i = SDL_LOG_PRIORITY_INVALID + 1; i < SDL_LOG_PRIORITY_COUNT; ++i) {
         if (SDL_strncasecmp(string, SDL_priority_names[i], length) == 0) {
             *priority = (SDL_LogPriority)i;
             return true;
@@ -327,7 +330,7 @@ static void ParseLogPriorities(const char *hint)
 {
     const char *name, *next;
     int category = DEFAULT_CATEGORY;
-    SDL_LogPriority priority = SDL_LOG_PRIORITY_COUNT;
+    SDL_LogPriority priority = SDL_LOG_PRIORITY_INVALID;
 
     if (SDL_strchr(hint, '=') == NULL) {
         if (ParseLogPriority(hint, SDL_strlen(hint), &priority)) {
@@ -427,7 +430,7 @@ static void CleanupLogPrefixes(void)
 
 static const char *GetLogPriorityPrefix(SDL_LogPriority priority)
 {
-    if (priority < SDL_LOG_PRIORITY_VERBOSE || priority >= SDL_LOG_PRIORITY_COUNT) {
+    if (priority <= SDL_LOG_PRIORITY_INVALID || priority >= SDL_LOG_PRIORITY_COUNT) {
         return "";
     }
 
@@ -485,6 +488,15 @@ void SDL_Log(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
     va_end(ap);
 }
 
+void SDL_LogTrace(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    SDL_LogMessageV(category, SDL_LOG_PRIORITY_TRACE, fmt, ap);
+    va_end(ap);
+}
+
 void SDL_LogVerbose(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
 {
     va_list ap;
diff --git a/src/dynapi/SDL_dynapi.c b/src/dynapi/SDL_dynapi.c
index f963c396dbb0f..ce170ba4a12b9 100644
--- a/src/dynapi/SDL_dynapi.c
+++ b/src/dynapi/SDL_dynapi.c
@@ -168,6 +168,7 @@ static void SDL_InitDynamicAPI(void);
         jump_table.SDL_LogMessageV(category, priority, fmt, ap);                                                                          \
         va_end(ap);                                                                                                                       \
     }                                                                                                                                     \
+    SDL_DYNAPI_VARARGS_LOGFN(_static, name, initcall, Trace, TRACE)                                                                   \
     SDL_DYNAPI_VARARGS_LOGFN(_static, name, initcall, Verbose, VERBOSE)                                                                   \
     SDL_DYNAPI_VARARGS_LOGFN(_static, name, initcall, Debug, DEBUG)                                                                       \
     SDL_DYNAPI_VARARGS_LOGFN(_static, name, initcall, Info, INFO)                                                                         \
@@ -317,6 +318,7 @@ static void SDLCALL SDL_LogMessage_LOGSDLCALLS(int category, SDL_LogPriority pri
         SDL_LogMessageV_REAL(category, SDL_LOG_PRIORITY_##prio, fmt, ap);                                           \
         va_end(ap);                                                                                                 \
     }
+SDL_DYNAPI_VARARGS_LOGFN_LOGSDLCALLS(Trace, TRACE)
 SDL_DYNAPI_VARARGS_LOGFN_LOGSDLCALLS(Verbose, VERBOSE)
 SDL_DYNAPI_VARARGS_LOGFN_LOGSDLCALLS(Debug, DEBUG)
 SDL_DYNAPI_VARARGS_LOGFN_LOGSDLCALLS(Info, INFO)
diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym
index a1268d580a484..389a5644c5138 100644
--- a/src/dynapi/SDL_dynapi.sym
+++ b/src/dynapi/SDL_dynapi.sym
@@ -629,6 +629,7 @@ SDL3_0.0.0 {
     SDL_LogInfo;
     SDL_LogMessage;
     SDL_LogMessageV;
+    SDL_LogTrace;
     SDL_LogVerbose;
     SDL_LogWarn;
     SDL_MapGPUTransferBuffer;
diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h
index 341e316c728d8..14193f0f34308 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -654,6 +654,7 @@
 #define SDL_LogInfo SDL_LogInfo_REAL
 #define SDL_LogMessage  SDL_LogMessage_REAL
 #define SDL_LogMessageV SDL_LogMessageV_REAL
+#define SDL_LogTrace SDL_LogTrace_REAL
 #define SDL_LogVerbose  SDL_LogVerbose_REAL
 #define SDL_LogWarn SDL_LogWarn_REAL
 #define SDL_MapGPUTransferBuffer SDL_MapGPUTransferBuffer_REAL
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index ae2a1e4ddc37c..eacfbc71e3a81 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -37,6 +37,7 @@ SDL_DYNAPI_PROC(void,SDL_LogDebug,(int a, SDL_PRINTF_FORMAT_STRING const char *b
 SDL_DYNAPI_PROC(void,SDL_LogError,(int a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),)
 SDL_DYNAPI_PROC(void,SDL_LogInfo,(int a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),)
 SDL_DYNAPI_PROC(void,SDL_LogMessage,(int a, SDL_LogPriority b, SDL_PRINTF_FORMAT_STRING const char *c, ...),(a,b,c),)
+SDL_DYNAPI_PROC(void,SDL_LogTrace,(int a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),)
 SDL_DYNAPI_PROC(void,SDL_LogVerbose,(int a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),)
 SDL_DYNAPI_PROC(void,SDL_LogWarn,(int a, SDL_PRINTF_FORMAT_STRING const char *b, ...),(a,b),)
 SDL_DYNAPI_PROC(SDL_bool,SDL_SetError,(SDL_PRINTF_FORMAT_STRING const char *a, ...),(a),return)
diff --git a/test/testautomation_log.c b/test/testautomation_log.c
index 184030bcfdc31..2ab192962055f 100644
--- a/test/testautomation_log.c
+++ b/test/testautomation_log.c
@@ -138,8 +138,8 @@ static int SDLCALL log_testHint(void *arg)
 
     }
 
-    SDL_SetHint(SDL_HINT_LOGGING, "0=4,3=2,2=0,*=3");
-    SDLTest_AssertPass("SDL_SetHint(SDL_HINT_LOGGING, \"0=4,3=2,2=0,*=3\")");
+    SDL_SetHint(SDL_HINT_LOGGING, "0=5,3=3,2=0,*=4");
+    SDLTest_AssertPass("SDL_SetHint(SDL_HINT_LOGGING, \"0=5,3=3,2=1,*=4\")");
     {
         EnableTestLog(&count);
         SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "test");