diff --git a/gcml.h b/gcml.h index e5000fa..c3de6d2 100644 --- a/gcml.h +++ b/gcml.h @@ -311,4 +311,123 @@ #define CONTAINER_OF(ptr, type, member) \ ((type *)((char *)(ptr) - OFFSET_OF(type, member))) + +// ------------------------- +// Additional Utility Macros +// ------------------------- + +/** + * @brief Safely reallocates memory and checks for allocation failure. + * @param ptr The pointer to the previously allocated memory. + * @param size The new size in bytes to allocate. + */ +#define SAFE_REALLOC(ptr, size) do { \ + void* _tmp = realloc((ptr), (size)); \ + if ((_tmp) == NULL) { \ + LOG_FATAL("Memory reallocation failed for size %zu", (size_t)(size)); \ + } else { \ + (ptr) = _tmp; \ + } \ +} while (0) + +/** + * @brief Marks a function as unused to suppress compiler warnings. + */ +#define UNUSED_FUNCTION __attribute__((unused)) + +/** + * @brief Converts a value to a string at compile time. + * @param value The value to stringify. + * @return The string representation of the value. + */ +#define TO_STRING(value) TOSTRING(value) + +/** + * @brief Generates a unique identifier by appending the line number. + * @param prefix The prefix for the identifier. + * @return A unique identifier. + */ +#define UNIQUE_ID(prefix) CONCAT(prefix, __LINE__) + +/** + * @brief Forces a value to evaluate to a specific type without altering its binary representation. + * @param value The value to cast. + * @param type The target type. + * @return The value cast to the specified type. + */ +#define FORCE_CAST(value, type) (*(type*)&(value)) + +/** + * @brief Creates a do-while loop that executes exactly once. + * @param block The block of code to execute. + */ +#define EXECUTE_ONCE(block) do { block } while(0) + +/** + * @brief Checks if a pointer is aligned to a specified boundary. + * @param ptr The pointer to check. + * @param align The alignment boundary (must be a power of two). + * @return Non-zero if aligned, zero otherwise. + */ +#define IS_ALIGNED(ptr, align) ((((uintptr_t)(const void*)(ptr)) & ((align) - 1)) == 0) + +/** + * @brief Calculates the number of bits set to 1 in a variable. + * @param x The variable to count bits in. + * @return The number of bits set to 1. + */ +#define COUNT_SET_BITS(x) (__builtin_popcount(x)) + +/** + * @brief Calculates the ceiling of a division between two integers. + * @param numerator The numerator. + * @param denominator The denominator. + * @return The ceiling of the division. + */ +#define CEIL_DIV(numerator, denominator) (((numerator) + (denominator) - 1) / (denominator)) + +/** + * @brief Concatenates two tokens with an underscore. + * @param a The first token. + * @param b The second token. + * @return The concatenated token separated by an underscore. + */ +#define CONCAT_WITH_UNDERSCORE(a, b) CONCAT(a, _##b) + +/** + * @brief Swaps two variables without using a temporary variable (only for integer types). + * @param a The first variable. + * @param b The second variable. + */ +#define SWAP_INPLACE(a, b) do { \ + (a) ^= (b); \ + (b) ^= (a); \ + (a) ^= (b); \ +} while (0) + +// ------------------------- +// Safe Reallocation Macro +// ------------------------- + +/** + * @brief Safely reallocates memory and checks for allocation failure. + * @param ptr The pointer to the previously allocated memory. + * @param size The new size in bytes to allocate. + */ +#define SAFE_REALLOC(ptr, size) do { \ + void* _tmp = realloc((ptr), (size)); \ + if ((_tmp) == NULL) { \ + LOG_FATAL("Memory reallocation failed for size %zu", (size_t)(size)); \ + } else { \ + (ptr) = _tmp; \ + } \ +} while (0) + + + + #endif // COMMON_MACROS_H + + + +