gcml/Docs.md
2024-12-24 05:38:34 +00:00

12 KiB

gcml.h Documentation

gcml.h is a comprehensive C/C++ header file that provides a collection of powerful and versatile macros designed to simplify common programming tasks. These macros enhance code readability, maintainability, and efficiency by encapsulating repetitive patterns and providing utility functions for various operations such as debugging, logging, memory management, and more.


Table of Contents

  1. General Utility Macros
  2. Debugging and Logging Macros
  3. Assertion Macros
  4. Stringification Macros
  5. Token Pasting Macros
  6. Memory Management Macros
  7. Type Casting Macros
  8. Bit Manipulation Macros
  9. Compile-Time Assertion Macro
  10. Deprecation Warning Macros
  11. Loop Macros
  12. Swap Macros
  13. Execute Once Macros
  14. Additional Utility Macros
  15. Utility Macros
  16. Best Practices and Considerations

1. General Utility Macros

MIN(a, b)

Description:
Returns the smaller of two values a and b.

Usage Example:

int a = 5, b = 10;
int min_val = MIN(a, b); // min_val = 5

MAX(a, b)

Description:
Returns the larger of two values a and b.

Usage Example:

int a = 5, b = 10;
int max_val = MAX(a, b); // max_val = 10

ARRAY_SIZE(arr)

Description:
Calculates the number of elements in an array arr.

Usage Example:

int arr[] = {1, 2, 3, 4, 5};
size_t size = ARRAY_SIZE(arr); // size = 5

UNUSED(x)

Description:
Suppresses compiler warnings for unused variables x.

Usage Example:

void func(int used, int unused) {
    UNUSED(unused);
    // Function implementation
}

ALIGN_UP(x, align)

Description:
Aligns a value x upwards to the nearest multiple of align.

Usage Example:

size_t aligned = ALIGN_UP(13, 8); // aligned = 16

ALIGN_DOWN(x, align)

Description:
Aligns a value x downwards to the nearest multiple of align.

Usage Example:

size_t aligned = ALIGN_DOWN(13, 8); // aligned = 8

2. Debugging and Logging Macros

DEBUG_PRINT(fmt, ...)

Description:
Prints debug messages with file name, line number, and function name. Only active when DEBUG is defined.

Usage Example:

DEBUG_PRINT("Value of x: %d", x);

LOG_INFO(fmt, ...)

Description:
Logs informational messages to stdout.

Usage Example:

LOG_INFO("Application started successfully.");

LOG_WARN(fmt, ...)

Description:
Logs warning messages to stderr.

Usage Example:

LOG_WARN("Low memory detected.");

LOG_ERROR(fmt, ...)

Description:
Logs error messages to stderr.

Usage Example:

LOG_ERROR("Failed to open file: %s", filename);

LOG_FATAL(fmt, ...)

Description:
Logs fatal error messages to stderr and exits the program.

Usage Example:

LOG_FATAL("Unrecoverable error occurred.");

3. Assertion Macros

ASSERT(cond, fmt, ...)

Description:
Asserts a condition cond and logs an error message if the condition is false. Only active when NDEBUG is not defined.

Usage Example:

ASSERT(ptr != NULL, "Pointer 'ptr' should not be NULL.");

4. Stringification Macros

STRINGIFY(x)

Description:
Converts a macro argument x to a string literal.

Usage Example:

#define VERSION 1
const char* version_str = STRINGIFY(VERSION); // "1"

TOSTRING(x)

Description:
Ensures that x is expanded before stringification.

Usage Example:

#define VERSION_MAJOR 2
#define VERSION_MINOR 5
const char* version = TOSTRING(VERSION_MAJOR) "." TOSTRING(VERSION_MINOR); // "2.5"

5. Token Pasting Macros

CONCAT(a, b)

Description:
Concatenates two tokens a and b.

Usage Example:

int CONCAT(temp, 1) = 10; // Expands to temp1

CONCAT3(a, b, c)

Description:
Concatenates three tokens a, b, and c.

Usage Example:

int CONCAT3(var, _, 1) = 20; // Expands to var_1

6. Memory Management Macros

SAFE_MALLOC(ptr, size)

Description:
Allocates memory of size bytes and assigns it to ptr. Logs a fatal error and exits if allocation fails.

Usage Example:

int *array = NULL;
SAFE_MALLOC(array, sizeof(int) * 10);
// Use array...
SAFE_FREE(array);

SAFE_CALLOC(ptr, count, type)

Description:
Allocates zero-initialized memory for count elements of type type and assigns it to ptr. Logs a fatal error and exits if allocation fails.

Usage Example:

int *array = NULL;
SAFE_CALLOC(array, 10, int);
// Use array...
SAFE_FREE(array);

SAFE_FREE(ptr)

Description:
Frees the memory pointed to by ptr and sets ptr to NULL to prevent dangling pointers.

Usage Example:

SAFE_FREE(array);

7. Type Casting Macros

SAFE_CAST(ptr, type)

Description:
Safely casts a pointer ptr to a specified type type.

Usage Example:

void *generic_ptr = malloc(sizeof(int));
int *int_ptr = SAFE_CAST(generic_ptr, int*);

8. Bit Manipulation Macros

SET_BIT(x, pos)

Description:
Sets the bit at position pos in variable x.

Usage Example:

unsigned int flags = 0;
SET_BIT(flags, 2); // Sets the 3rd bit

CLEAR_BIT(x, pos)

Description:
Clears the bit at position pos in variable x.

Usage Example:

CLEAR_BIT(flags, 2); // Clears the 3rd bit

TOGGLE_BIT(x, pos)

Description:
Toggles the bit at position pos in variable x.

Usage Example:

TOGGLE_BIT(flags, 1); // Toggles the 2nd bit

CHECK_BIT(x, pos)

Description:
Checks if the bit at position pos in variable x is set. Returns a non-zero value if set, zero otherwise.

Usage Example:

if (CHECK_BIT(flags, 1)) {
    LOG_INFO("Bit 1 is set.");
}

9. Compile-Time Assertion Macro

STATIC_ASSERT(expr, msg)

Description:
Performs a compile-time assertion to ensure that expr is true. If not, compilation fails with the message msg.

Usage Example:

STATIC_ASSERT(sizeof(int) == 4, "Integer size is not 4 bytes.");

10. Deprecation Warning Macros

DEPRECATED(msg)

Description:
Marks a function or variable as deprecated with a custom message msg. This provides a compiler warning when the deprecated entity is used.

Usage Example:

DEPRECATED("Use new_function() instead.")
void old_function() {
    LOG_WARN("This function is deprecated.");
}

11. Loop Macros

FOREACH(item, array)

Description:
Iterates over each element in an array array, assigning each element's address to item.

Usage Example:

int arr[] = {1, 2, 3, 4, 5};
int *item;
FOREACH(item, arr) {
    LOG_INFO("Array element: %d", *item);
}

REPEAT(n, block)

Description:
Repeats a block of code n times.

Usage Example:

REPEAT(3, {
    LOG_INFO("Repeating this message.");
});

12. Swap Macros

SWAP(a, b)

Description:
Swaps the values of two variables a and b. Both variables must be of the same type.

Usage Example:

int a = 10, b = 20;
SWAP(a, b);
// Now a = 20, b = 10

SWAP_INPLACE(a, b)

Description:
Swaps the values of two integer variables a and b without using a temporary variable. Uses XOR bitwise operations.

Usage Example:

int x = 5, y = 10;
SWAP_INPLACE(x, y);
// Now x = 10, y = 5

Note: This macro is limited to integer types and should be used with caution to avoid undefined behavior.


13. Execute Once Macros

DO_ONCE(block)

Description:
Executes a block of code block only once, regardless of how many times the macro is called.

Usage Example:

DO_ONCE({
    LOG_INFO("This message is printed only once.");
});

DO_ONCE({
    LOG_INFO("This message will not be printed again.");
});

EXECUTE_ONCE(block)

Description:
Creates a do-while loop that executes a block of code block exactly once.

Usage Example:

EXECUTE_ONCE({
    initialize_system();
});

14. Additional Utility Macros

SAFE_REALLOC(ptr, size)

Description:
Reallocates memory for pointer ptr to a new size size bytes. Logs a fatal error and exits if reallocation fails.

Usage Example:

int *data = malloc(5 * sizeof(int));
// Initialize data...

// Reallocate to hold more integers
SAFE_REALLOC(data, 10 * sizeof(int));

// Use the reallocated data...

SAFE_FREE(data);

UNUSED_FUNCTION

Description:
Marks a function as unused to suppress compiler warnings about unused functions.

Usage Example:

UNUSED_FUNCTION void debug_helper() {
    DEBUG_PRINT("This is a debug helper function.");
}

TO_STRING(value)

Description:
Converts a value value to a string at compile time.

Usage Example:

#define VERSION_MAJOR 2
#define VERSION_MINOR 5

const char* version = TO_STRING(VERSION_MAJOR) "." TO_STRING(VERSION_MINOR);
// version = "2.5"

UNIQUE_ID(prefix)

Description:
Generates a unique identifier by appending the current line number to a given prefix.

Usage Example:

int UNIQUE_ID(temp_) = 100; // Expands to temp_23 if on line 23

FORCE_CAST(value, type)

Description:
Forces a value value to evaluate to a specific type type without altering its binary representation.

Usage Example:

float f = 3.14f;
int i = FORCE_CAST(f, int); // Reinterprets the bits of f as an int

Warning:
This macro performs a low-level operation and can lead to undefined behavior if misused.


IS_ALIGNED(ptr, align)

Description:
Checks if a pointer ptr is aligned to a specified boundary align. Returns a non-zero value if aligned, zero otherwise.

Usage Example:

int x;
if (IS_ALIGNED(&x, 4)) {
    LOG_INFO("Variable x is 4-byte aligned.");
}

COUNT_SET_BITS(x)

Description:
Counts the number of bits set to 1 in the integer x.

Usage Example:

unsigned int flags = 0b1011;
int count = COUNT_SET_BITS(flags); // count = 3

CEIL_DIV(numerator, denominator)

Description:
Calculates the ceiling of the division between two integers numerator and denominator.

Usage Example:

int pages = CEIL_DIV(total_items, items_per_page);

CONCAT_WITH_UNDERSCORE(a, b)

Description:
Concatenates two tokens a and b with an underscore _ separating them.

Usage Example:

int CONCAT_WITH_UNDERSCORE(var, 1) = 50; // Expands to var_1

15. Utility Macros

OFFSET_OF(type, member)

Description:
Calculates the byte offset of a member member within a struct of type type.

Usage Example:

typedef struct {
    int id;
    char name[50];
} Person;

size_t offset = OFFSET_OF(Person, name); // Offset of 'name' within 'Person'

CONTAINER_OF(ptr, type, member)

Description:
Retrieves the pointer to the containing struct from a member pointer ptr. Given the type type and member member, it calculates the address of the parent struct.

Usage Example:

typedef struct {
    int id;
    char name[50];
} Person;

Person person = {1, "Alice"};
int *id_ptr = &person.id;
Person *p = CONTAINER_OF(id_ptr, Person, id);
// p points to 'person'