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; } }
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_stream_standard_destroy(struct logger_stream *inst) { logger_assert(NULL != inst); logger_memory_free(inst->buffer); inst->buffer = NULL; inst->buffer_size = 0; return LOGGER_SUCCESS; }
void logger_list_clear(struct logger_list *inst) { logger_assert(NULL != inst); struct logger_list_node *it; struct logger_list_node *next; for (it = inst->first; it != NULL; it = next) { next = it->next; logger_memory_free(it); } *inst = LOGGER_LIST_INIT; }
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; }
void logger_list_remove_node(struct logger_list *inst, struct logger_list_node *node) { logger_assert(NULL != inst); if ((NULL == inst->first) || (NULL == node)) return; if ((node == inst->first) && (node == inst->last)) { inst->first = NULL; inst->last = NULL; } else if (node == inst->first) { inst->first = node->next; } else if (node == inst->last) { inst->last = node->prev; } else { struct logger_list_node *after = node->next; struct logger_list_node *before = node->prev; after->prev = before; before->next = after; } logger_memory_free(node); }
void logger_destroy(struct logger *inst) { if (NULL != inst) { logger_list_clear(&inst->stream_list); logger_memory_free(inst); } }