Skip to content

Commit

Permalink
Private function documentation and minor refactoring
Browse files Browse the repository at this point in the history
* Documented the private functions of the Message Logger. That way, it 
should be easier for others to understand how this logger was built;
* Private function prototypes now contain the argument names for each 
argument;
* Renamed a private function and improved it's comments;
  • Loading branch information
AndreLaranjeira committed Nov 12, 2021
1 parent e7ddffb commit 413d278
Showing 1 changed file with 294 additions and 12 deletions.
306 changes: 294 additions & 12 deletions src/message_logger.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
//!
//! <b>Warning:</b> 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.
//!
//! <b>Important:</b> 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!
//!
//! <b>Warning:</b> 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
//!
//! <b>Important:</b> This function should receive a log_file pointer that is
//! NOT NULL to work as expected. Otherwise, it will have NO EFFECT!
//!
//! <b>Important:</b> 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.
//!
//! <b>Warning:</b> 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.
//!
//! <b>Important:</b> 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) {
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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");
}

Expand Down

0 comments on commit 413d278

Please sign in to comment.