/*
 * find_byte_widths.c
 * Introspects type sizes for HDF5 configuration (R Package Build).
 *
 * This generator outputs the "Default" sizes based on the machine performing
 * the build. These definitions are intended to be included by H5pubconf.h,
 * which may override them using compiler macros (e.g. __SIZEOF_INT__) to
 * support cross-compilation or universal binary builds.
 */

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <time.h>
#include <sys/types.h>

/* Helper to detect endianness at runtime */
int is_little_endian(void) {
    int x = 1;
    return *(char *)&x;
}

int main(void) {
    printf("#ifndef H5_BYTE_WIDTHS_H\n");
    printf("#define H5_BYTE_WIDTHS_H\n\n");
    printf("/* Generated by find_byte_widths.c */\n\n");

    /* 1. Standard C Integers */
    printf("#define H5_SIZEOF_CHAR %d\n", (int)sizeof(char));
    printf("#define H5_SIZEOF_SHORT %d\n", (int)sizeof(short));
    printf("#define H5_SIZEOF_INT %d\n", (int)sizeof(int));
    printf("#define H5_SIZEOF_UNSIGNED %d\n", (int)sizeof(unsigned));
    printf("#define H5_SIZEOF_LONG %d\n", (int)sizeof(long));
    printf("#define H5_SIZEOF_LONG_LONG %d\n", (int)sizeof(long long));
    
    /* 2. Floating Point */
    printf("#define H5_SIZEOF_FLOAT %d\n", (int)sizeof(float));
    printf("#define H5_SIZEOF_DOUBLE %d\n", (int)sizeof(double));
    printf("#define H5_SIZEOF_LONG_DOUBLE %d\n", (int)sizeof(long double));

    /* 3. C99 Complex Types */
    printf("#define H5_SIZEOF_FLOAT_COMPLEX %d\n", (int)sizeof(float _Complex));
    printf("#define H5_SIZEOF_DOUBLE_COMPLEX %d\n", (int)sizeof(double _Complex));
    printf("#define H5_SIZEOF_LONG_DOUBLE_COMPLEX %d\n", (int)sizeof(long double _Complex));

    /* 4. Boolean */
    printf("#define H5_SIZEOF_BOOL %d\n", (int)sizeof(bool));

    /* 5. System Types */
    printf("#define H5_SIZEOF_SIZE_T %d\n", (int)sizeof(size_t));
    printf("#define H5_SIZEOF_PTRDIFF_T %d\n", (int)sizeof(ptrdiff_t));
    printf("#define H5_SIZEOF_TIME_T %d\n", (int)sizeof(time_t));

    /* 6. POSIX Types */
    printf("#define H5_SIZEOF_OFF_T %d\n", (int)sizeof(off_t));
    printf("#define H5_SIZEOF_SSIZE_T %d\n", (int)sizeof(ssize_t));

    /* 7. stdint.h Types */
    printf("#define H5_SIZEOF_INT8_T %d\n", (int)sizeof(int8_t));
    printf("#define H5_SIZEOF_UINT8_T %d\n", (int)sizeof(uint8_t));
    printf("#define H5_SIZEOF_INT16_T %d\n", (int)sizeof(int16_t));
    printf("#define H5_SIZEOF_UINT16_T %d\n", (int)sizeof(uint16_t));
    printf("#define H5_SIZEOF_INT32_T %d\n", (int)sizeof(int32_t));
    printf("#define H5_SIZEOF_UINT32_T %d\n", (int)sizeof(uint32_t));
    printf("#define H5_SIZEOF_INT64_T %d\n", (int)sizeof(int64_t));
    printf("#define H5_SIZEOF_UINT64_T %d\n", (int)sizeof(uint64_t));

    printf("#define H5_SIZEOF_INT_FAST8_T %d\n", (int)sizeof(int_fast8_t));
    printf("#define H5_SIZEOF_UINT_FAST8_T %d\n", (int)sizeof(uint_fast8_t));
    printf("#define H5_SIZEOF_INT_FAST16_T %d\n", (int)sizeof(int_fast16_t));
    printf("#define H5_SIZEOF_UINT_FAST16_T %d\n", (int)sizeof(uint_fast16_t));
    printf("#define H5_SIZEOF_INT_FAST32_T %d\n", (int)sizeof(int_fast32_t));
    printf("#define H5_SIZEOF_UINT_FAST32_T %d\n", (int)sizeof(uint_fast32_t));
    printf("#define H5_SIZEOF_INT_FAST64_T %d\n", (int)sizeof(int_fast64_t));
    printf("#define H5_SIZEOF_UINT_FAST64_T %d\n", (int)sizeof(uint_fast64_t));

    printf("#define H5_SIZEOF_INT_LEAST8_T %d\n", (int)sizeof(int_least8_t));
    printf("#define H5_SIZEOF_UINT_LEAST8_T %d\n", (int)sizeof(uint_least8_t));
    printf("#define H5_SIZEOF_INT_LEAST16_T %d\n", (int)sizeof(int_least16_t));
    printf("#define H5_SIZEOF_UINT_LEAST16_T %d\n", (int)sizeof(uint_least16_t));
    printf("#define H5_SIZEOF_INT_LEAST32_T %d\n", (int)sizeof(int_least32_t));
    printf("#define H5_SIZEOF_UINT_LEAST32_T %d\n", (int)sizeof(uint_least32_t));
    printf("#define H5_SIZEOF_INT_LEAST64_T %d\n", (int)sizeof(int_least64_t));
    printf("#define H5_SIZEOF_UINT_LEAST64_T %d\n", (int)sizeof(uint_least64_t));

    /* 8. Disable Float16 */
    printf("#define H5_SIZEOF__FLOAT16 0\n");

    /* 9. Endianness (Runtime Default) */
    if (is_little_endian()) {
        printf("#undef WORDS_BIGENDIAN\n");
    } else {
        printf("#define WORDS_BIGENDIAN 1\n");
    }

    printf("\n#endif /* H5_BYTE_WIDTHS_H */\n");
    return 0;
}
