more APIs

This commit is contained in:
InoriRus
2022-04-13 20:36:34 +10:00
parent 1d43b81773
commit 08b0a87225
134 changed files with 49099 additions and 96 deletions
+26
View File
@@ -0,0 +1,26 @@
Copyright (C) 2018 Marat Dukhan
Copyright (c) 2017-2018 Facebook Inc.
Copyright (c) 2017 Georgia Institute of Technology
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+100
View File
@@ -0,0 +1,100 @@
#pragma once
#include <stdarg.h>
#include <stdlib.h>
#include <inttypes.h>
#define CLOG_NONE 0
#define CLOG_FATAL 1
#define CLOG_ERROR 2
#define CLOG_WARNING 3
#define CLOG_INFO 4
#define CLOG_DEBUG 5
#ifndef CLOG_VISIBILITY
#if defined(__ELF__)
#define CLOG_VISIBILITY __attribute__((__visibility__("internal")))
#elif defined(__MACH__)
#define CLOG_VISIBILITY __attribute__((__visibility__("hidden")))
#else
#define CLOG_VISIBILITY
#endif
#endif
#ifndef CLOG_ARGUMENTS_FORMAT
#if defined(__GNUC__)
#define CLOG_ARGUMENTS_FORMAT __attribute__((__format__(__printf__, 1, 2)))
#else
#define CLOG_ARGUMENTS_FORMAT
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
CLOG_VISIBILITY void clog_vlog_debug(const char* module, const char* format, va_list args);
CLOG_VISIBILITY void clog_vlog_info(const char* module, const char* format, va_list args);
CLOG_VISIBILITY void clog_vlog_warning(const char* module, const char* format, va_list args);
CLOG_VISIBILITY void clog_vlog_error(const char* module, const char* format, va_list args);
CLOG_VISIBILITY void clog_vlog_fatal(const char* module, const char* format, va_list args);
#define CLOG_DEFINE_LOG_DEBUG(log_debug_function_name, module, level) \
CLOG_ARGUMENTS_FORMAT \
inline static void log_debug_function_name(const char* format, ...) { \
if (level >= CLOG_DEBUG) { \
va_list args; \
va_start(args, format); \
clog_vlog_debug(module, format, args); \
va_end(args); \
} \
}
#define CLOG_DEFINE_LOG_INFO(log_info_function_name, module, level) \
CLOG_ARGUMENTS_FORMAT \
inline static void log_info_function_name(const char* format, ...) { \
if (level >= CLOG_INFO) { \
va_list args; \
va_start(args, format); \
clog_vlog_info(module, format, args); \
va_end(args); \
} \
}
#define CLOG_DEFINE_LOG_WARNING(log_warning_function_name, module, level) \
CLOG_ARGUMENTS_FORMAT \
inline static void log_warning_function_name(const char* format, ...) { \
if (level >= CLOG_WARNING) { \
va_list args; \
va_start(args, format); \
clog_vlog_warning(module, format, args); \
va_end(args); \
} \
}
#define CLOG_DEFINE_LOG_ERROR(log_error_function_name, module, level) \
CLOG_ARGUMENTS_FORMAT \
inline static void log_error_function_name(const char* format, ...) { \
if (level >= CLOG_ERROR) { \
va_list args; \
va_start(args, format); \
clog_vlog_error(module, format, args); \
va_end(args); \
} \
}
#define CLOG_DEFINE_LOG_FATAL(log_fatal_function_name, module, level) \
CLOG_ARGUMENTS_FORMAT \
inline static void log_fatal_function_name(const char* format, ...) { \
if (level >= CLOG_FATAL) { \
va_list args; \
va_start(args, format); \
clog_vlog_fatal(module, format, args); \
va_end(args); \
} \
abort(); \
}
#ifdef __cplusplus
} /* extern "C" */
#endif
+423
View File
@@ -0,0 +1,423 @@
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
#ifdef __ANDROID__
#include <android/log.h>
#endif
#ifndef CLOG_LOG_TO_STDIO
#ifdef __ANDROID__
#define CLOG_LOG_TO_STDIO 0
#else
#define CLOG_LOG_TO_STDIO 1
#endif
#endif
#include <clog.h>
/* Messages up to this size are formatted entirely on-stack, and don't allocate heap memory */
#define CLOG_STACK_BUFFER_SIZE 1024
#define CLOG_FATAL_PREFIX "Fatal error: "
#define CLOG_FATAL_PREFIX_LENGTH 13
#define CLOG_FATAL_PREFIX_FORMAT "Fatal error in %s: "
#define CLOG_ERROR_PREFIX "Error: "
#define CLOG_ERROR_PREFIX_LENGTH 7
#define CLOG_ERROR_PREFIX_FORMAT "Error in %s: "
#define CLOG_WARNING_PREFIX "Warning: "
#define CLOG_WARNING_PREFIX_LENGTH 9
#define CLOG_WARNING_PREFIX_FORMAT "Warning in %s: "
#define CLOG_INFO_PREFIX "Note: "
#define CLOG_INFO_PREFIX_LENGTH 6
#define CLOG_INFO_PREFIX_FORMAT "Note (%s): "
#define CLOG_DEBUG_PREFIX "Debug: "
#define CLOG_DEBUG_PREFIX_LENGTH 7
#define CLOG_DEBUG_PREFIX_FORMAT "Debug (%s): "
#define CLOG_SUFFIX_LENGTH 1
void clog_vlog_fatal(const char* module, const char* format, va_list args) {
#if defined(__ANDROID__) && !CLOG_LOG_TO_STDIO
__android_log_vprint(ANDROID_LOG_FATAL, module, format, args);
#else
char stack_buffer[CLOG_STACK_BUFFER_SIZE];
char* heap_buffer = NULL;
char* out_buffer = &stack_buffer[0];
/* The first call to vsnprintf will clobber args, thus need a copy in case a second vsnprintf call is needed */
va_list args_copy;
va_copy(args_copy, args);
int prefix_chars = CLOG_FATAL_PREFIX_LENGTH;
if (module == NULL) {
memcpy(stack_buffer, CLOG_FATAL_PREFIX, CLOG_FATAL_PREFIX_LENGTH);
} else {
prefix_chars = snprintf(stack_buffer, CLOG_STACK_BUFFER_SIZE, CLOG_FATAL_PREFIX_FORMAT, module);
if (prefix_chars < 0) {
/* Format error in prefix (possible if prefix is modified): skip prefix and continue as if nothing happened. */
prefix_chars = 0;
}
}
int format_chars;
if (prefix_chars + CLOG_SUFFIX_LENGTH >= CLOG_STACK_BUFFER_SIZE) {
/*
* Prefix + suffix alone would overflow the on-stack buffer, thus need to use on-heap buffer.
* Do not even try to format the string into on-stack buffer.
*/
format_chars = vsnprintf(NULL, 0, format, args);
} else {
format_chars =
vsnprintf(
&stack_buffer[prefix_chars],
CLOG_STACK_BUFFER_SIZE - prefix_chars - CLOG_SUFFIX_LENGTH,
format,
args);
}
if (format_chars < 0) {
/* Format error in the message: silently ignore this particular message. */
goto cleanup;
}
if (prefix_chars + format_chars + CLOG_SUFFIX_LENGTH > CLOG_STACK_BUFFER_SIZE) {
/* Allocate a buffer on heap, and vsnprintf to this buffer */
heap_buffer = malloc(prefix_chars + format_chars + CLOG_SUFFIX_LENGTH);
if (heap_buffer == NULL) {
goto cleanup;
}
if (prefix_chars > CLOG_STACK_BUFFER_SIZE) {
/* Prefix didn't fit into on-stack buffer, re-format it again to on-heap buffer */
snprintf(heap_buffer, prefix_chars + 1 /* for '\0'-terminator */, CLOG_FATAL_PREFIX_FORMAT, module);
} else {
/* Copy pre-formatted prefix from on-stack buffer to on-heap buffer */
memcpy(heap_buffer, stack_buffer, prefix_chars);
}
vsnprintf(heap_buffer + prefix_chars, format_chars + CLOG_SUFFIX_LENGTH, format, args_copy);
out_buffer = heap_buffer;
}
out_buffer[prefix_chars + format_chars] = '\n';
#ifdef _WIN32
DWORD bytes_written;
WriteFile(
GetStdHandle(STD_ERROR_HANDLE),
out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH,
&bytes_written, NULL);
#else
write(STDERR_FILENO, out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH);
#endif
cleanup:
free(heap_buffer);
va_end(args_copy);
#endif
}
void clog_vlog_error(const char* module, const char* format, va_list args) {
#if defined(__ANDROID__) && !CLOG_LOG_TO_STDIO
__android_log_vprint(ANDROID_LOG_ERROR, module, format, args);
#else
char stack_buffer[CLOG_STACK_BUFFER_SIZE];
char* heap_buffer = NULL;
char* out_buffer = &stack_buffer[0];
/* The first call to vsnprintf will clobber args, thus need a copy in case a second vsnprintf call is needed */
va_list args_copy;
va_copy(args_copy, args);
int prefix_chars = CLOG_ERROR_PREFIX_LENGTH;
if (module == NULL) {
memcpy(stack_buffer, CLOG_ERROR_PREFIX, CLOG_ERROR_PREFIX_LENGTH);
} else {
prefix_chars = snprintf(stack_buffer, CLOG_STACK_BUFFER_SIZE, CLOG_ERROR_PREFIX_FORMAT, module);
if (prefix_chars < 0) {
/* Format error in prefix (possible if prefix is modified): skip prefix and continue as if nothing happened. */
prefix_chars = 0;
}
}
int format_chars;
if (prefix_chars + CLOG_SUFFIX_LENGTH >= CLOG_STACK_BUFFER_SIZE) {
/*
* Prefix + suffix alone would overflow the on-stack buffer, thus need to use on-heap buffer.
* Do not even try to format the string into on-stack buffer.
*/
format_chars = vsnprintf(NULL, 0, format, args);
} else {
format_chars =
vsnprintf(
&stack_buffer[prefix_chars],
CLOG_STACK_BUFFER_SIZE - prefix_chars - CLOG_SUFFIX_LENGTH,
format,
args);
}
if (format_chars < 0) {
/* Format error in the message: silently ignore this particular message. */
goto cleanup;
}
if (prefix_chars + format_chars + CLOG_SUFFIX_LENGTH > CLOG_STACK_BUFFER_SIZE) {
/* Allocate a buffer on heap, and vsnprintf to this buffer */
heap_buffer = malloc(prefix_chars + format_chars + CLOG_SUFFIX_LENGTH);
if (heap_buffer == NULL) {
goto cleanup;
}
if (prefix_chars > CLOG_STACK_BUFFER_SIZE) {
/* Prefix didn't fit into on-stack buffer, re-format it again to on-heap buffer */
snprintf(heap_buffer, prefix_chars + 1 /* for '\0'-terminator */, CLOG_ERROR_PREFIX_FORMAT, module);
} else {
/* Copy pre-formatted prefix from on-stack buffer to on-heap buffer */
memcpy(heap_buffer, stack_buffer, prefix_chars);
}
vsnprintf(heap_buffer + prefix_chars, format_chars + CLOG_SUFFIX_LENGTH, format, args_copy);
out_buffer = heap_buffer;
}
out_buffer[prefix_chars + format_chars] = '\n';
#ifdef _WIN32
DWORD bytes_written;
WriteFile(
GetStdHandle(STD_ERROR_HANDLE),
out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH,
&bytes_written, NULL);
#else
write(STDERR_FILENO, out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH);
#endif
cleanup:
free(heap_buffer);
va_end(args_copy);
#endif
}
void clog_vlog_warning(const char* module, const char* format, va_list args) {
#if defined(__ANDROID__) && !CLOG_LOG_TO_STDIO
__android_log_vprint(ANDROID_LOG_WARN, module, format, args);
#else
char stack_buffer[CLOG_STACK_BUFFER_SIZE];
char* heap_buffer = NULL;
char* out_buffer = &stack_buffer[0];
/* The first call to vsnprintf will clobber args, thus need a copy in case a second vsnprintf call is needed */
va_list args_copy;
va_copy(args_copy, args);
int prefix_chars = CLOG_WARNING_PREFIX_LENGTH;
if (module == NULL) {
memcpy(stack_buffer, CLOG_WARNING_PREFIX, CLOG_WARNING_PREFIX_LENGTH);
} else {
prefix_chars = snprintf(stack_buffer, CLOG_STACK_BUFFER_SIZE, CLOG_WARNING_PREFIX_FORMAT, module);
if (prefix_chars < 0) {
/* Format error in prefix (possible if prefix is modified): skip prefix and continue as if nothing happened. */
prefix_chars = 0;
}
}
int format_chars;
if (prefix_chars + CLOG_SUFFIX_LENGTH >= CLOG_STACK_BUFFER_SIZE) {
/*
* Prefix + suffix alone would overflow the on-stack buffer, thus need to use on-heap buffer.
* Do not even try to format the string into on-stack buffer.
*/
format_chars = vsnprintf(NULL, 0, format, args);
} else {
format_chars =
vsnprintf(
&stack_buffer[prefix_chars],
CLOG_STACK_BUFFER_SIZE - prefix_chars - CLOG_SUFFIX_LENGTH,
format,
args);
}
if (format_chars < 0) {
/* Format error in the message: silently ignore this particular message. */
goto cleanup;
}
if (prefix_chars + format_chars + CLOG_SUFFIX_LENGTH > CLOG_STACK_BUFFER_SIZE) {
/* Allocate a buffer on heap, and vsnprintf to this buffer */
heap_buffer = malloc(prefix_chars + format_chars + CLOG_SUFFIX_LENGTH);
if (heap_buffer == NULL) {
goto cleanup;
}
if (prefix_chars > CLOG_STACK_BUFFER_SIZE) {
/* Prefix didn't fit into on-stack buffer, re-format it again to on-heap buffer */
snprintf(heap_buffer, prefix_chars + 1 /* for '\0'-terminator */, CLOG_WARNING_PREFIX_FORMAT, module);
} else {
/* Copy pre-formatted prefix from on-stack buffer to on-heap buffer */
memcpy(heap_buffer, stack_buffer, prefix_chars);
}
vsnprintf(heap_buffer + prefix_chars, format_chars + CLOG_SUFFIX_LENGTH, format, args_copy);
out_buffer = heap_buffer;
}
out_buffer[prefix_chars + format_chars] = '\n';
#ifdef _WIN32
DWORD bytes_written;
WriteFile(
GetStdHandle(STD_ERROR_HANDLE),
out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH,
&bytes_written, NULL);
#else
write(STDERR_FILENO, out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH);
#endif
cleanup:
free(heap_buffer);
va_end(args_copy);
#endif
}
void clog_vlog_info(const char* module, const char* format, va_list args) {
#if defined(__ANDROID__) && !CLOG_LOG_TO_STDIO
__android_log_vprint(ANDROID_LOG_INFO, module, format, args);
#else
char stack_buffer[CLOG_STACK_BUFFER_SIZE];
char* heap_buffer = NULL;
char* out_buffer = &stack_buffer[0];
/* The first call to vsnprintf will clobber args, thus need a copy in case a second vsnprintf call is needed */
va_list args_copy;
va_copy(args_copy, args);
int prefix_chars = CLOG_INFO_PREFIX_LENGTH;
if (module == NULL) {
memcpy(stack_buffer, CLOG_INFO_PREFIX, CLOG_INFO_PREFIX_LENGTH);
} else {
prefix_chars = snprintf(stack_buffer, CLOG_STACK_BUFFER_SIZE, CLOG_INFO_PREFIX_FORMAT, module);
if (prefix_chars < 0) {
/* Format error in prefix (possible if prefix is modified): skip prefix and continue as if nothing happened. */
prefix_chars = 0;
}
}
int format_chars;
if (prefix_chars + CLOG_SUFFIX_LENGTH >= CLOG_STACK_BUFFER_SIZE) {
/*
* Prefix + suffix alone would overflow the on-stack buffer, thus need to use on-heap buffer.
* Do not even try to format the string into on-stack buffer.
*/
format_chars = vsnprintf(NULL, 0, format, args);
} else {
format_chars =
vsnprintf(
&stack_buffer[prefix_chars],
CLOG_STACK_BUFFER_SIZE - prefix_chars - CLOG_SUFFIX_LENGTH,
format,
args);
}
if (format_chars < 0) {
/* Format error in the message: silently ignore this particular message. */
goto cleanup;
}
if (prefix_chars + format_chars + CLOG_SUFFIX_LENGTH > CLOG_STACK_BUFFER_SIZE) {
/* Allocate a buffer on heap, and vsnprintf to this buffer */
heap_buffer = malloc(prefix_chars + format_chars + CLOG_SUFFIX_LENGTH);
if (heap_buffer == NULL) {
goto cleanup;
}
if (prefix_chars > CLOG_STACK_BUFFER_SIZE) {
/* Prefix didn't fit into on-stack buffer, re-format it again to on-heap buffer */
snprintf(heap_buffer, prefix_chars + 1 /* for '\0'-terminator */, CLOG_INFO_PREFIX_FORMAT, module);
} else {
/* Copy pre-formatted prefix from on-stack buffer to on-heap buffer */
memcpy(heap_buffer, stack_buffer, prefix_chars);
}
vsnprintf(heap_buffer + prefix_chars, format_chars + CLOG_SUFFIX_LENGTH, format, args_copy);
out_buffer = heap_buffer;
}
out_buffer[prefix_chars + format_chars] = '\n';
#ifdef _WIN32
DWORD bytes_written;
WriteFile(
GetStdHandle(STD_OUTPUT_HANDLE),
out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH,
&bytes_written, NULL);
#else
write(STDOUT_FILENO, out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH);
#endif
cleanup:
free(heap_buffer);
va_end(args_copy);
#endif
}
void clog_vlog_debug(const char* module, const char* format, va_list args) {
#if defined(__ANDROID__) && !CLOG_LOG_TO_STDIO
__android_log_vprint(ANDROID_LOG_DEBUG, module, format, args);
#else
char stack_buffer[CLOG_STACK_BUFFER_SIZE];
char* heap_buffer = NULL;
char* out_buffer = &stack_buffer[0];
/* The first call to vsnprintf will clobber args, thus need a copy in case a second vsnprintf call is needed */
va_list args_copy;
va_copy(args_copy, args);
int prefix_chars = CLOG_DEBUG_PREFIX_LENGTH;
if (module == NULL) {
memcpy(stack_buffer, CLOG_DEBUG_PREFIX, CLOG_DEBUG_PREFIX_LENGTH);
} else {
prefix_chars = snprintf(stack_buffer, CLOG_STACK_BUFFER_SIZE, CLOG_DEBUG_PREFIX_FORMAT, module);
if (prefix_chars < 0) {
/* Format error in prefix (possible if prefix is modified): skip prefix and continue as if nothing happened. */
prefix_chars = 0;
}
}
int format_chars;
if (prefix_chars + CLOG_SUFFIX_LENGTH >= CLOG_STACK_BUFFER_SIZE) {
/*
* Prefix + suffix alone would overflow the on-stack buffer, thus need to use on-heap buffer.
* Do not even try to format the string into on-stack buffer.
*/
format_chars = vsnprintf(NULL, 0, format, args);
} else {
format_chars =
vsnprintf(
&stack_buffer[prefix_chars],
CLOG_STACK_BUFFER_SIZE - prefix_chars - CLOG_SUFFIX_LENGTH,
format,
args);
}
if (format_chars < 0) {
/* Format error in the message: silently ignore this particular message. */
goto cleanup;
}
if (prefix_chars + format_chars + CLOG_SUFFIX_LENGTH > CLOG_STACK_BUFFER_SIZE) {
/* Allocate a buffer on heap, and vsnprintf to this buffer */
heap_buffer = malloc(prefix_chars + format_chars + CLOG_SUFFIX_LENGTH);
if (heap_buffer == NULL) {
goto cleanup;
}
if (prefix_chars > CLOG_STACK_BUFFER_SIZE) {
/* Prefix didn't fit into on-stack buffer, re-format it again to on-heap buffer */
snprintf(heap_buffer, prefix_chars + 1 /* for '\0'-terminator */, CLOG_DEBUG_PREFIX_FORMAT, module);
} else {
/* Copy pre-formatted prefix from on-stack buffer to on-heap buffer */
memcpy(heap_buffer, stack_buffer, prefix_chars);
}
vsnprintf(heap_buffer + prefix_chars, format_chars + CLOG_SUFFIX_LENGTH, format, args_copy);
out_buffer = heap_buffer;
}
out_buffer[prefix_chars + format_chars] = '\n';
#ifdef _WIN32
DWORD bytes_written;
WriteFile(
GetStdHandle(STD_OUTPUT_HANDLE),
out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH,
&bytes_written, NULL);
#else
write(STDOUT_FILENO, out_buffer, prefix_chars + format_chars + CLOG_SUFFIX_LENGTH);
#endif
cleanup:
free(heap_buffer);
va_end(args_copy);
#endif
}