diff --git a/src/util/log.c b/src/util/log.c index 7dfe11cb704..e0f2a900c27 100644 --- a/src/util/log.c +++ b/src/util/log.c @@ -29,8 +29,11 @@ #include #endif +#include +#include #include "util/detect_os.h" #include "util/log.h" +#include "util/ralloc.h" #ifdef ANDROID static inline android_LogPriority @@ -90,3 +93,68 @@ mesa_log_v(enum mesa_log_level level, const char *tag, const char *format, #endif #endif } + +struct log_stream * +_mesa_log_stream_create(enum mesa_log_level level, char *tag) +{ + struct log_stream *stream = ralloc(NULL, struct log_stream); + stream->level = level; + stream->tag = tag; + stream->msg = ralloc_strdup(stream, ""); + stream->pos = 0; + return stream; +} + +void +mesa_log_stream_destroy(struct log_stream *stream) +{ + /* If you left trailing stuff in the log stream, flush it out as a line. */ + if (stream->pos != 0) + mesa_log(stream->level, stream->tag, "%s", stream->msg); + + ralloc_free(stream); +} + +static void +mesa_log_stream_flush(struct log_stream *stream, size_t scan_offset) +{ + char *end; + char *next = stream->msg; + while ((end = strchr(stream->msg + scan_offset, '\n'))) { + *end = 0; + mesa_log(stream->level, stream->tag, "%s", next); + next = end + 1; + scan_offset = next - stream->msg; + } + if (next != stream->msg) { + /* Clear out the lines we printed and move any trailing chars to the start. */ + size_t remaining = stream->msg + stream->pos - next; + memmove(stream->msg, next, remaining); + stream->pos = remaining; + } +} + +void mesa_log_stream_printf(struct log_stream *stream, const char *format, ...) +{ + size_t old_pos = stream->pos; + + va_list va; + va_start(va, format); + ralloc_vasprintf_rewrite_tail(&stream->msg, &stream->pos, format, va); + va_end(va); + + mesa_log_stream_flush(stream, old_pos); +} + +void +_mesa_log_multiline(enum mesa_log_level level, const char *tag, const char *lines) +{ + struct log_stream tmp = { + .level = level, + .tag = tag, + .msg = strdup(lines), + .pos = strlen(lines), + }; + mesa_log_stream_flush(&tmp, 0); + free(tmp.msg); +} diff --git a/src/util/log.h b/src/util/log.h index b1190f4068b..ccd00d627c0 100644 --- a/src/util/log.h +++ b/src/util/log.h @@ -68,6 +68,22 @@ mesa_log_v(enum mesa_log_level, const char *tag, const char *format, #define mesa_logd_v(fmt, va) __mesa_log_use_args((fmt), (va)) #endif +struct log_stream { + char *msg; + const char *tag; + size_t pos; + enum mesa_log_level level; +}; + +struct log_stream *_mesa_log_stream_create(enum mesa_log_level level, char *tag); +#define mesa_log_streame() _mesa_log_stream_create(MESA_LOG_ERROR, (MESA_LOG_TAG)) +#define mesa_log_streamw() _mesa_log_stream_create(MESA_LOG_WARN, (MESA_LOG_TAG)) +#define mesa_log_streami() _mesa_log_stream_create(MESA_LOG_INFO, (MESA_LOG_TAG)) +void mesa_log_stream_destroy(struct log_stream *stream); +void mesa_log_stream_printf(struct log_stream *stream, const char *format, ...); + +void _mesa_log_multiline(enum mesa_log_level level, const char *tag, const char *lines); +#define mesa_log_multiline(level, lines) _mesa_log_multiline(level, (MESA_LOG_TAG), lines) #ifndef DEBUG /* Suppres -Wunused */