diff --git a/src/message_logger.c b/src/message_logger.c index 8dc7a09..296938b 100644 --- a/src/message_logger.c +++ b/src/message_logger.c @@ -31,15 +31,297 @@ static TimeFormat logger_time_fmt = { }; // Private function prototypes: + +//! \fn static void apply_all_default_attributes() +//! \brief Reset all the terminal's colors and text attributes to their +//! defaults. +//! +//! This function resets all of the terminal's colors and text attributes to +//! the default configurations specified for the terminal. This includes the +//! colors used for text font and text background, the font weight and any +//! other characteristics configured using ANSI escape codes. +//! +//! Usage example: +//! \code +//! // Change various text configurations. +//! apply_all_default_attributes(); +//! \endcode static void apply_all_default_attributes(); -static void clear_line_background_past_cursor(); -static void copy_display_colors(DisplayColors*, const DisplayColors*); -static void log_formatted_text_content(FILE*, const char*, va_list); -static void log_message(FILE*, TimeFormat*, const char*, const char*, - const char*, va_list); -static void log_timestamp(FILE*, TimeFormat*); -static void print_context(const char*); -static void print_formatted_text(const char*, va_list); + +//! \fn static void clear_line_text_background_past_cursor() +//! \brief Clears the existing colored text background past the cursor in the +//! current line. +//! +//! This function clears any existing colored text background past the cursor +//! position in the current line. When a line break occurs in the terminal, the +//! new line is entirely colored with the current text background color. +//! Therefore, when any change in the text background color occurs, it is +//! necessary to clear the text background in the current line past the cursor +//! position to allow the new text background color to take effect. +//! +//! Usage example: +//! \code +//! // Color the text's background with a certain color. +//! // Color the text's background with another color. +//! clear_line_text_background_past_cursor(); +//! \endcode +static void clear_line_text_background_past_cursor(); + +//! \fn static void copy_display_colors( +//! DisplayColors* destination, +//! const DisplayColors* origin +//! ) +//! \brief Copies data between DisplayColors variables. Both pointers MUST NOT +//! be NULL! +//! \param destination Destination for data to be copied to. Must NOT be NULL! +//! \param origin Source for data to be copied from. Must NOT be NULL! +//! +//! This function copies data between two DisplayColors variables, duplicating +//! any and all data. This includes the data stored in pointers. +//! +//! This function exists because, while the assignment operator may be used to +//! copy the contents of a struct, that copying process doesn't duplicate the +//! contents of a pointer, instead copying the same pointer to another struct. +//! Therefore, this function should be used to avoid getting possible pointer +//! duplicates when copying DisplayColors data structures. +//! +//! Warning: This functions does not check if both pointers are valid! +//! Do NOT call this function with NULL pointers. +//! +//! Usage example: +//! \code +//! DisplayColors origin, destination; +//! +//! origin.text_color = B_GRN; +//! origin.background_color = B_WHT; +//! +//! copy_display_colors(&destination, &origin); +//! \endcode +static void copy_display_colors( + DisplayColors* destination, + const DisplayColors* origin +); + +//! \fn static void log_formatted_text_content( +//! FILE* log_file, +//! const char* text_format, +//! va_list text_args +//! ) +//! \brief Writes a formatted text with it's arguments to a log file. Log file +//! pointer must NOT be NULL. +//! \param log_file Log file where text will be logged. Must NOT be NULL. +//! \param text_format String formatting for the text's contents before +//! argument substitution takes place. +//! \param text_args Arguments used to substitute placeholders in the text's +//! contents. +//! +//! This function writes a formatted text to a log file, utilizing the +//! arguments provided to substitute any placeholders in the text's initial +//! format. +//! +//! Important: The va_list provided as an argument for this function is +//! NOT rendered unusable by this function! A local copy of the va_list +//! argument is made, allowing other functions to reuse it. However, this +//! implies that the memory cleaning for the va_list achieved with va_end() is +//! a task that this function does NOT handle! +//! +//! Warning: This functions does not check if the file pointer is valid! +//! Do NOT call this function with a NULL file pointer. +//! +//! Usage example: +//! \code +//! FILE *log_file; +//! +//! void question(const char* text_format, ...) { +//! va_list text_args; +//! va_start(text_args, text_format); +//! log_formatted_text_content( +//! log_file, +//! text_format, +//! text_args +//! ); +//! va_end(text_args); +//! } +//! +//! int main() { +//! int num = 3; +//! log_file = fopen("test-logfile.log", "w"); +//! // Use the question function. The text should be logged correctly. +//! question("Number %d: What is the mitochondria?", int); +//! fclose(log_file); +//! return 0; +//! } +//! \endcode +static void log_formatted_text_content( + FILE* log_file, + const char* text_format, + va_list text_args +); + +//! \fn static void log_message( +//! FILE* log_file, +//! TimeFormat* time_format, +//! const char* msg_context, +//! const char* msg_type, +//! const char* msg_format, +//! va_list msg_args +//! ) +//! \brief Writes a text message with it's timestamp information to a log file. +//! Log file pointer must NOT be NULL. +//! \param log_file File where message will be logged. Must NOT be NULL. +//! \param time_format Time format used to generate timestamp in the log file. +//! \param msg_context Text containing the message's caller context. Pass a +//! NULL pointer to log a message without context. +//! \param msg_type Text that identifies the type of message logged. +//! \param msg_format Message's text format without substitution arguments. +//! \param msg_args Arguments to substitute in message's text format. +//! +//! This function writes a timestamped message to a log file. The timestamp +//! formatting and contents is determined by the time_format argument. To log a +//! message, the conventional structure of context, type and format is +//! required, as this structure is used by all default message types provided +//! by the Message Logger module. +//! +//! If we indicate the contents of a variable by "${VARIABLE}", we can state +//! that a typical message logged will appear like so: +//! \verbatim [${TIMESTAMP}] ${CONTEXT}: ${TYPE} ${MESSAGE_TEXT} \endverbatim +//! +//! An example of a logged message in the sample file appears below: +//! \verbatim [23:17:15] Main: (Success) Thread 1 finished! \endverbatim +//! +//! Important: This function should receive a log_file pointer that is +//! NOT NULL to work as expected. Otherwise, it will have NO EFFECT! +//! +//! Important: The va_list provided as an argument for this function is +//! NOT rendered unusable by this function! All functions called by this +//! function and that utilize the va_list argument should make a local copy of +//! it, allowing other functions to reuse it. However, this implies that the +//! memory cleaning for the va_list achieved with va_end() is a task that this +//! function does NOT handle! +//! +//! Usage example: +//! \code +//! FILE *log_file; +//! TimeFormat time_format = { +//! .string_representation = "%H:%M:%S" +//! }; +//! +//! void question(const char* context, const char* text_format, ...) { +//! va_list text_args; +//! va_start(text_args, text_format); +//! log_message( +//! log_file, +//! &time_format, +//! context, +//! "(Question)", +//! text_format, +//! text_args +//! ); +//! va_end(text_args); +//! } +//! +//! int main() { +//! int num = 3; +//! log_file = fopen("test-logfile.log", "w"); +//! // Use the question function. The question should be logged correctly in +//! // the expected message format and with a timestamp. +//! question("Biology test", "Number %d: What is the mitochondria?", int); +//! fclose(log_file); +//! return 0; +//! } +//! \endcode +static void log_message( + FILE* log_file, + TimeFormat* time_format, + const char* msg_context, + const char* msg_type, + const char* msg_format, + va_list msg_args +); + +//! \fn static void log_timestamp(FILE* log_file, TimeFormat* time_format) +//! \brief Writes a timestamp to a log file with a certain format. Log file +//! pointer must NOT be NULL. +//! \param log_file File where timestamp will be logged. Must NOT be NULL. +//! \param time_format Time format used to generate timestamp. +//! +//! This function writes a timestamp to a log file. The time_format argument +//! determines the formatting and contents of the timestamp. This function is +//! generally called by functions that write message's contents to a log file +//! (e.g: the \link log_message() log_message \endlink function) to register +//! the time in which the message was generated by the Message Logger module. +//! +//! Warning: This functions does not check if the file pointer is valid! +//! Do NOT call this function with a NULL file pointer. +//! +//! Usage example: +//! \code +//! FILE *log_file; +//! TimeFormat time_format = { +//! .string_representation = "%H:%M:%S" +//! }; +//! +//! int main() { +//! log_file = fopen("test-logfile.log", "w"); +//! log_timestamp(log_file, &time_format); +//! fprintf(log_file, "This message is being logged and timestamped!\n"); +//! fclose(log_file); +//! return 0; +//! } +//! \endcode +static void log_timestamp(FILE* log_file, TimeFormat* time_format); + +//! \fn static void print_context(const char *context) +//! \brief Prints a message's caller context in tag format. +//! \param context Text containing the message's caller context. +//! +//! This function writes the context tag of a message to the terminal. The +//! colors used for the context tag are taken from the Message Logger's +//! LoggerColorPallet. +//! +//! Usage example: +//! \code +//! print_context("Main function"); +//! printf("This message came from the main function!\n"); +//! \endcode +static void print_context(const char *context); + +//! \fn static void print_formatted_text( +//! const char* text_format, +//! va_list text_args +//! ) +//! \brief Prints a formatted text after argument substitution. +//! \param text_format String formatting for the text's contents before +//! argument substitution takes place. +//! \param text_args Arguments used to substitute placeholders in the text's +//! contents. +//! +//! This function writes a formatted text to the terminal, utilizing the +//! arguments provided to substitute any placeholders in the text's initial +//! format. +//! +//! Important: The va_list provided as an argument for this function is +//! NOT rendered unusable by this function! A local copy of the va_list +//! argument is made, allowing other functions to reuse it. However, this +//! implies that the memory cleaning for the va_list achieved with va_end() is +//! a task that this function does NOT handle! +//! +//! Usage example: +//! \code +//! void question(const char* text_format, ...) { +//! va_list text_args; +//! va_start(text_args, text_format); +//! print_formatted_text(text_format, text_args); +//! va_end(text_args); +//! } +//! +//! int main() { +//! int num = 3; +//! question("Number %d: What is the mitochondria?", int); +//! return 0; +//! } +//! \endcode +static void print_formatted_text(const char* text_format, va_list text_args); // Public function implementations: int configure_log_file(const char *file_name, LogFileMode file_mode) { @@ -385,7 +667,7 @@ void color_background(Color p_color) { } - clear_line_background_past_cursor(); + clear_line_text_background_past_cursor(); // Release logger recursive lock if thread safety is enabled: if(logger_recursive_mutex != NULL) @@ -662,7 +944,7 @@ void reset_colors() { pthread_mutex_lock(logger_recursive_mutex); apply_all_default_attributes(); - clear_line_background_past_cursor(); + clear_line_text_background_past_cursor(); // Release logger recursive lock if thread safety is enabled: if(logger_recursive_mutex != NULL) @@ -822,10 +1104,10 @@ static void apply_all_default_attributes() { printf("\x1B[0m"); } -static void clear_line_background_past_cursor() { +static void clear_line_text_background_past_cursor() { // When bash creates a new line, it colors the background of the entire new // line automatically. The following printf clears any existing background - // on the current line. + // on the current line past the cursor position. printf("\x1B[K"); }