static void __vlog_write(struct logger *inst, const unsigned int level, const char *file_name, const char *function_name, const unsigned int line_number, const char *fmt, va_list args) { if (false == inst->options.option.output_enable) return; if (inst->options.option.level < level) return; va_list args_copy; va_copy(args_copy, args); /* Get how much bytes to allocate for message string */ int message_length = vsnprintf(NULL, 0, fmt, args_copy); va_end(args_copy); if (message_length < 0) return; /* Create logger message object extended with message string */ size_t size = sizeof(struct logger_stream_message) + (size_t)message_length + 1; struct logger_stream_message *msg = logger_memory_alloc(size); if (NULL == msg) return; /* Put formatted string to logger message object */ if (vsnprintf(msg->message, (size_t)message_length, fmt, args) < 0) { logger_memory_free(msg); return; } __log_write(inst, level, file_name, function_name, line_number, msg, size); }
int logger_list_push(struct logger_list *inst, void *object, int id) { logger_assert(NULL != inst); struct logger_list_node *node = logger_memory_alloc(sizeof(struct logger_list_node)); if (NULL == node) { return LOGGER_ERROR_NULL; } node->next = NULL; node->prev = NULL; node->object = object; node->id = id; if (NULL == inst->first) { inst->first = node; inst->last = node; } else { inst->last->next = node; node->prev = inst->last; inst->last = node; } return LOGGER_SUCCESS; }
static void __log_write(struct logger *inst, const unsigned int level, const char *file_name, const char *function_name, const unsigned int line_number, struct logger_stream_message *msg, const size_t size) { int err; /* Additional debug information */ if (true == inst->options.option.more_debug) { /* We don't need to allocate memory for string, because constant string * are located in read-only section by the compiler/linker and they * have non-volatile constant address that will never change during * whole program execution */ msg->line_number = line_number; msg->file_name = (NULL == file_name) ? "" : file_name; msg->function_name = (NULL == function_name) ? "" : function_name; } /* Set log level, tag, flags and time stamp format */ msg->tag = inst->tag; msg->options.raw = inst->options.raw; msg->options.option.level = LOG_LEVEL_MASK & level; /* Re-stamp log time */ logger_time_update(&msg->log_time); struct logger_list_node *it; struct logger_stream_message *msg_copy = NULL; /* When more than one stream object present in the list, * processing other stream objects with new copy message, because * other streams can handle message with different speed */ for (it = inst->stream_list.first; NULL != it; it = it->next) { if (NULL != it->next) { msg_copy = logger_memory_alloc(size); if (NULL != msg_copy) { memcpy_s(msg_copy, size, msg, size); } else { logger_memory_free(msg); return; } } err = logger_stream_add_message(it->object, msg, LOGGER_MESSAGE_STREAM_WRITE); if (err) { logger_memory_free(msg); logger_memory_free(msg_copy); return; } msg = msg_copy; msg_copy = NULL; } }
char *logger_alloc_copy_string(const char *str) { logger_assert(NULL != str); size_t size = strnlen_s(str, RSIZE_MAX_STR); char *buffer = logger_memory_alloc(size + 1); if (NULL != buffer) { strncpy_s(buffer, RSIZE_MAX_STR, str, size); buffer[size] = '\0'; } return buffer; }
struct logger *logger_create(const char *tag, union logger_options *options) { /* Default values */ struct logger *inst = logger_memory_alloc(sizeof(struct logger)); if (NULL != inst) { memset(inst, 0, sizeof(struct logger)); if (NULL != options) { inst->options.raw = options->raw; } else { inst->options.raw = g_logger_default_options.raw; } inst->tag = tag; } return inst; }
int logger_stream_standard_create(struct logger_stream *inst) { logger_assert(NULL != inst); logger_memory_free(inst->buffer); /* Extend buffer size for null terminator character */ inst->buffer = logger_memory_alloc(LOGGER_DEFAULT_STREAM_SIZE + 1); if (NULL != inst->buffer) { inst->buffer_size = LOGGER_DEFAULT_STREAM_SIZE; } else { inst->buffer_size = 0; return LOGGER_ERROR_NULL; } return LOGGER_SUCCESS; }
char *logger_alloc_fmt_string(const char *fmt, va_list args) { logger_assert(NULL != fmt); va_list args_copy; va_copy(args_copy, args); char *buffer = NULL; int size = vsnprintf(NULL, 0, fmt, args); if (size > 0) { buffer = logger_memory_alloc((size_t)size + 1); if (NULL != buffer) { vsnprintf(buffer, (size_t)size, fmt, args_copy); } } va_end(args_copy); return buffer; }
void _log_write(struct logger *inst, const unsigned int level, const char *file_name, const char *function_name, const unsigned int line_number, const char *message) { logger_assert(NULL != inst); size_t message_length = strnlen_s(message, RSIZE_MAX_STR); size_t size = sizeof(struct logger_stream_message) + message_length + 1; struct logger_stream_message *msg = logger_memory_alloc(size); if (NULL == msg) { return; } memcpy_s(msg->message, message_length, message, message_length); msg->message[message_length] = '\0'; __log_write(inst, level, file_name, function_name, line_number, msg, size); }