#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#if defined(_MSC_VER)
#include <malloc.h>
#elif !defined(__MINGW64__)
#include <alloca.h>
#endif
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
#include <stdalign.h>
#include <stddef.h>
#define GUARANTEED_ALIGN alignof(max_align_t)
#elif defined(__GNUC__) || defined(__clang__)
#include <stddef.h>
#if defined(__SIZEOF_MAX_ALIGN_T__)
#define GUARANTEED_ALIGN __alignof__(max_align_t)
#elif defined(__MINGW64__) || defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64)
#define GUARANTEED_ALIGN 16
#else
#define GUARANTEED_ALIGN __alignof__(long double)
#endif
#elif defined(_MSC_VER)
#if defined(_M_X64) || defined(_M_AMD64)
#define GUARANTEED_ALIGN 16
#else
#define GUARANTEED_ALIGN 8
#endif
#else
#define GUARANTEED_ALIGN 16
#endif
#if defined(_MSC_VER)
#define ALLOCA(sz) _alloca(sz)
#else
#define ALLOCA(sz) alloca(sz)
#endif
void c_alloca(
const size_t size,
const size_t align,
void (*callback)(void*, uint8_t*, void*),
void* closure,
void* out
) {
size_t alloc_size = size;
size_t align_m_1;
bool need_padding = (align > GUARANTEED_ALIGN);
if (need_padding) {
align_m_1 = align - 1;
alloc_size += align_m_1;
}
uint8_t *ptr = (uint8_t*)ALLOCA(alloc_size);
if (need_padding) {
uintptr_t mask = (uintptr_t)(align_m_1);
ptr = (uint8_t*)(((uintptr_t)ptr + mask) & ~mask);
}
callback(closure, ptr, out);
}