|
@@ -109,3 +109,103 @@ void SDLTest_LogError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
|
|
|
/* Log with timestamp and newline */
|
|
|
SDL_LogMessage(SDL_LOG_CATEGORY_TEST, SDL_LOG_PRIORITY_ERROR, "%s: %s", SDLTest_TimestampToString(time(0)), logMessage);
|
|
|
}
|
|
|
+
|
|
|
+static char nibble_to_char(Uint8 nibble)
|
|
|
+{
|
|
|
+ if (nibble < 0xa) {
|
|
|
+ return '0' + nibble;
|
|
|
+ } else {
|
|
|
+ return 'a' + nibble - 10;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void SDLTest_LogEscapedString(const char *prefix, const void *buffer, size_t size)
|
|
|
+{
|
|
|
+ const Uint8 *data = buffer;
|
|
|
+ char logMessage[SDLTEST_MAX_LOGMESSAGE_LENGTH];
|
|
|
+
|
|
|
+ if (data) {
|
|
|
+ size_t i;
|
|
|
+ size_t pos = 0;
|
|
|
+ #define NEED_X_CHARS(N) \
|
|
|
+ if (pos + (N) > sizeof(logMessage) - 2) { \
|
|
|
+ break; \
|
|
|
+ }
|
|
|
+
|
|
|
+ logMessage[pos++] = '"';
|
|
|
+ for (i = 0; i < size; i++) {
|
|
|
+ Uint8 c = data[i];
|
|
|
+ size_t pos_start = pos;
|
|
|
+ switch (c) {
|
|
|
+ case '\0':
|
|
|
+ NEED_X_CHARS(2);
|
|
|
+ logMessage[pos++] = '\\';
|
|
|
+ logMessage[pos++] = '0';
|
|
|
+ break;
|
|
|
+ case '"':
|
|
|
+ NEED_X_CHARS(2);
|
|
|
+ logMessage[pos++] = '\\';
|
|
|
+ logMessage[pos++] = '"';
|
|
|
+ break;
|
|
|
+ case '\n':
|
|
|
+ NEED_X_CHARS(2);
|
|
|
+ logMessage[pos++] = '\\';
|
|
|
+ logMessage[pos++] = 'n';
|
|
|
+ break;
|
|
|
+ case '\r':
|
|
|
+ NEED_X_CHARS(2);
|
|
|
+ logMessage[pos++] = '\\';
|
|
|
+ logMessage[pos++] = 'r';
|
|
|
+ break;
|
|
|
+ case '\t':
|
|
|
+ NEED_X_CHARS(2);
|
|
|
+ logMessage[pos++] = '\\';
|
|
|
+ logMessage[pos++] = 't';
|
|
|
+ break;
|
|
|
+ case '\f':
|
|
|
+ NEED_X_CHARS(2);
|
|
|
+ logMessage[pos++] = '\\';
|
|
|
+ logMessage[pos++] = 'f';
|
|
|
+ break;
|
|
|
+ case '\b':
|
|
|
+ NEED_X_CHARS(2);
|
|
|
+ logMessage[pos++] = '\\';
|
|
|
+ logMessage[pos++] = 'b';
|
|
|
+ break;
|
|
|
+ case '\\':
|
|
|
+ NEED_X_CHARS(2);
|
|
|
+ logMessage[pos++] = '\\';
|
|
|
+ logMessage[pos++] = '\\';
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ if (SDL_isprint(c)) {
|
|
|
+ NEED_X_CHARS(1);
|
|
|
+ logMessage[pos++] = c;
|
|
|
+ } else {
|
|
|
+ NEED_X_CHARS(4);
|
|
|
+ logMessage[pos++] = '\\';
|
|
|
+ logMessage[pos++] = 'x';
|
|
|
+ logMessage[pos++] = nibble_to_char(c >> 4);
|
|
|
+ logMessage[pos++] = nibble_to_char(c & 0xf);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (pos == pos_start) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (i < size) {
|
|
|
+ logMessage[sizeof(logMessage) - 4] = '.';
|
|
|
+ logMessage[sizeof(logMessage) - 3] = '.';
|
|
|
+ logMessage[sizeof(logMessage) - 2] = '.';
|
|
|
+ logMessage[sizeof(logMessage) - 1] = '\0';
|
|
|
+ } else {
|
|
|
+ logMessage[pos++] = '"';
|
|
|
+ logMessage[pos] = '\0';
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ SDL_strlcpy(logMessage, "(nil)", sizeof(logMessage));
|
|
|
+ }
|
|
|
+
|
|
|
+ SDLTest_Log("%s%s", prefix, logMessage);
|
|
|
+}
|