/* =====================================
 * Generated by Mod-c 0.26.5
 * MODULE utils
 * ===================================== */

#include "utils.h"

void utils(void);

/**
 * Mod-c
 * By M. Scott Reynolds
 * Date 20 February 2026
 *
 * utils.c - Portable helper functions and safe arithmetic utilities.
 */
#include "stddef.h"
#include "stdlib.h"
#include "string.h"
#include "limits.h"
#include "stdio.h"
#include "ctype.h"
/**
 * Portable replacement for strnlen (not in C89/C95, but very useful).
 * Returns the length of the string or maxlen if no null terminator found.
 */
size_t utils_strnlen(string s, size_t maxlen)
{
    size_t results = 0;
    if (s != nil)
    {
        const pchar z_l38_c11 = memchr(s, '\0', maxlen);
        if (z_l38_c11 != nil)
        {
            results = (size_t)(z_l38_c11 - s);
        }
        else
        {
            results = maxlen;
        }
    }
    /* return value captured before defers */
    size_t __ret_l45 = results;
    return __ret_l45;
}

/**
 * Portable replacement for strndup.
 * Allocates and returns a new null-terminated copy of the first n chars of s.
 * Returns NULL on allocation failure (caller must check).
 */
pchar utils_strndup(string s, size_t n)
{
    pchar new_str = nil;
    if (s != nil)
    {
        const size_t str_len_l59_c20 = utils_strnlen(s, n);
        new_str = malloc(str_len_l59_c20 + 1);
        if (new_str != nil)
        {
            memcpy(new_str, s, str_len_l59_c20);
            new_str[str_len_l59_c20] = '\0';
        }
    }
    /* return value captured before defers */
    pchar __ret_l66 = new_str;
    return __ret_l66;
}

/**
 * Integer power using exponentiation by squaring (positive exponents only) 
 * Checks for overflow before each multiplication.
 * Exits program on detected overflow.
 *
 * @param base  Base value (may be negative)
 * @param exp   Non-negative exponent
 * @return      base^exp if representable in long long
 */
LONG utils_power(LONG base, cardinal exponent)
{
    long_long result = 1;
    long_long b = base;
    cardinal exp = exponent;
    while (exp > 0)
    {
        {
            if (exp & (cardinal)1)
            {
                if (b != 0 && result > LLONG_MAX / b)
                {
                    fprintf(stderr, "ERROR: utils_power: multiplication overflow\n");
                    exit(1);
                }
                result *= b;
            }
            if (exp > (cardinal)1)
            {
                if (b != 0 && b > LLONG_MAX / b)
                {
                    fprintf(stderr, "ERROR: utils_power: squaring overflow\n");
                    exit(1);
                }
                b *= b;
            }
            exp >>= 1;
        }
    }
    /* return value captured before defers */
    LONG __ret_l105 = result;
    return __ret_l105;
}

/**
 * @brief   Safely multiplies two signed long long integers.
 * @details Checks for overflow before performing the multiplication.
 *          Uses the standard method of testing against LLONG_MAX / LLONG_MIN
 *          to detect cases where the result would exceed the representable range.
 *
 * @param   a        First operand
 * @param   b        Second operand
 * @return  The product a * b if it can be represented in long long.
 *          Exits the program with an error message on overflow.
 *
 * @note    Assumes two's complement (guaranteed in C11 for signed integers).
 *          Corectly handles the edge case LLONG_MIN * -1.
 */
long long utils_safe_multiply(long_long a, long_long b)
{
    if (a == 0 || b == 0)
    {
        /* return value captured before defers */
        long long __ret_l127 = 0;
        return __ret_l127;
    }
    if (a == LLONG_MIN && b == -(long_long)1)
    {
        fprintf(stderr, "ERROR: utils_safe_multiply: overflow - LLONG_MIN * -1 is not representable\n");
        exit(1);
    }
    if (b > 0)
    {
        if (a > 0)
        {
            if (a > LLONG_MAX / b)
            {
                fprintf(stderr, "ERROR: utils_safe_multiply: overflow (positive * positive)\n");
                exit(1);
            }
        }
        else
        {
            if (a < LLONG_MIN / b)
            {
                fprintf(stderr, "ERROR: utils_safe_multiply: overflow (negative * positive)\n");
                exit(1);
            }
        }
    }
    else
    {
        if (a > 0)
        {
            if (a > LLONG_MIN / b)
            {
                fprintf(stderr, "ERROR: utils_safe_multiply: overflow (positive * negative)\n");
                exit(1);
            }
        }
        else
        {
            if (a < LLONG_MAX / b)
            {
                fprintf(stderr, "ERROR: utils_safe_multiply: overflow (negative * negative)\n");
                exit(1);
            }
        }
    }
    /* return value captured before defers */
    long long __ret_l169 = a * b;
    return __ret_l169;
}

/**
 * Parse integer literal that may contain:
 *  - _ digit separators (ignored)
 *  - 0x / 0X   hexadecimal
 *  - 0o / 0O   octal
 *  - 0b / 0B   binary
 * Exits on overflow or invalid characters.
 */
long_long utils_parse_integer_literal(string literal, size_t length)
{
    int base = 10;
    size_t i = 0;
    long_long result = 0;
    const char* str = literal;
    size_t str_len = length;
    if (str == nil || str_len == 0)
    {
        /* return value captured before defers */
        long_long __ret_l190 = 0;
        return __ret_l190;
    }
    while (str_len > 0 && isspace((uchar)(*str)))
    {
        {
            str++;
            str_len--;
        }
    }
    if (str_len >= 2 && str[0] == '0')
    {
        const char p_l202_c14 = str[1];
        if (p_l202_c14 == 'x' || p_l202_c14 == 'X')
        {
            base = 16;
            i = 2;
        }
        else if (p_l202_c14 == 'o' || p_l202_c14 == 'O')
        {
            base = 8;
            i = 2;
        }
        else if (p_l202_c14 == 'b' || p_l202_c14 == 'B')
        {
            base = 2;
            i = 2;
        }
    }
    while (i < str_len)
    {
        {
            int digit = {0};
            const char c_l215_c14 = str[i];
            if (c_l215_c14 != '_')
            {
                if (isdigit((uchar)c_l215_c14))
                {
                    digit = c_l215_c14 - '0';
                }
                else if (base == 16 && c_l215_c14 >= 'a' && c_l215_c14 <= 'f')
                {
                    digit = 10 + (c_l215_c14 - 'a');
                }
                else if (base == 16 && c_l215_c14 >= 'A' && c_l215_c14 <= 'F')
                {
                    digit = 10 + (c_l215_c14 - 'A');
                }
                else
                {
                    fprintf(stderr, "ERROR: utils_parse_integer_literal: invalid digit '%c' in bases %d\n", c_l215_c14, base);
                    exit(1);
                }
                if (digit >= base)
                {
                    fprintf(stderr, "ERROR: utils_parse_integer_literal: digit '%c' out of range for base %d\n", c_l215_c14, base);
                    exit(1);
                }
                if (result > (LLONG_MAX - digit) / base)
                {
                    fprintf(stderr, "ERROR: utils_parse_integer_literal: integer overflow\n");
                    exit(1);
                }
                result = result * base + digit;
            }
            i++;
        }
    }
    /* return value captured before defers */
    long_long __ret_l242 = result;
    return __ret_l242;
}


void utils(void)
{
}
