Affix

 view release on metacpan or  search on metacpan

infix/src/core/utility.c  view on Meta::CPAN

/**
 * Copyright (c) 2025 Sanko Robinson
 *
 * This source code is dual-licensed under the Artistic License 2.0 or the MIT License.
 * You may choose to use this code under the terms of either license.
 *
 * SPDX-License-Identifier: (Artistic-2.0 OR MIT)
 *
 * The documentation blocks within this file are licensed under the
 * Creative Commons Attribution 4.0 International License (CC BY 4.0).
 *
 * SPDX-License-Identifier: CC-BY-4.0
 */
/**
 * @file utility.c
 * @brief Implements internal debugging utilities.
 * @ingroup internal_core
 *
 * @details This file provides the implementation for debugging functions that are
 * conditionally compiled only when the `INFIX_DEBUG_ENABLED` preprocessor macro
 * is defined and set to a non-zero value.
 *
 * In release builds, this entire translation unit is effectively empty, ensuring
 * that debugging code has no impact on the final binary's size or performance.
 * The corresponding function declarations in `utility.h` become empty inline
 * stubs, which are optimized away by the compiler.
 */
// This file is only compiled if debugging is enabled.
#if defined(INFIX_DEBUG_ENABLED) && INFIX_DEBUG_ENABLED
// Use the double-tap test harness's `note` macro for debug printing if available.
// This integrates the debug output seamlessly into the TAP test logs.
#if defined(DBLTAP_ENABLE) && defined(DBLTAP_IMPLEMENTATION)
#include "common/double_tap.h"
#else
// If not building as part of a test, fall back to a standard printf implementation.
#include <stdio.h>
#ifndef note
#define note(...)                 \
    do {                          \
        printf("# " __VA_ARGS__); \
        printf("\n");             \
    } while (0)
#endif
#endif  // DBLTAP_ENABLE
#include "common/utility.h"
#include <inttypes.h>
/**
 * @internal
 * @brief Dumps a block of memory to standard output in a standard hexadecimal format.
 *
 * @details This is an essential debugging tool for inspecting the machine code generated
 * by the JIT engine or for examining the memory layout of complex data structures.
 * The output is formatted similarly to common hex dump utilities, with a 16-byte
 * width, address offsets, hexadecimal bytes, and an ASCII representation.
 *
 * This function is only compiled in debug builds.
 *
 * @param data A pointer to the memory to dump.
 * @param size The number of bytes to dump.
 * @param title A descriptive title to print before the hex dump.
 */
void infix_dump_hex(const void * data, size_t size, const char * title) {
    const uint8_t * byte = (const uint8_t *)data;
    char line_buf[256];
    char * buf_ptr;
    size_t remaining_len;
    int written;
    note("%s (size: %llu bytes at %p)", title, (unsigned long long)size, data);
    for (size_t i = 0; i < size; i += 16) {
        buf_ptr = line_buf;
        remaining_len = sizeof(line_buf);
        // Print the address offset for the current line.
        written = snprintf(buf_ptr, remaining_len, "0x%04llx: ", (unsigned long long)i);
        if (written < 0 || (size_t)written >= remaining_len)
            goto print_line;
        buf_ptr += written;
        remaining_len -= written;
        // Print the hexadecimal representation of the bytes.
        for (size_t j = 0; j < 16; ++j) {
            if (i + j < size)
                written = snprintf(buf_ptr, remaining_len, "%02x ", byte[i + j]);
            else
                written = snprintf(buf_ptr, remaining_len, "   ");  // Pad if at the end of the data.
            if (written < 0 || (size_t)written >= remaining_len)
                goto print_line;
            buf_ptr += written;
            remaining_len -= written;
            if (j == 7) {  // Add an extra space in the middle for readability.
                written = snprintf(buf_ptr, remaining_len, " ");
                if (written < 0 || (size_t)written >= remaining_len)
                    goto print_line;



( run in 0.551 second using v1.01-cache-2.11-cpan-97f6503c9c8 )