#ifndef INCBIN_H
#define INCBIN_H

#if COMPILER_MSVC

/* ========================== *
 * Msvc RC file incbin
 *
 * NOTE: Msvc doesn't have an inline assembler that can include binary data.
 * So instead these macros will trigger a lookup into the embedded RC file for
 * entries matched by name (requires the build system to generate and link RC
 * file).
 * ========================== */

#define INCBIN_INCLUDE(var, _rc_name) static struct _incbin_rc_resource _incbin_ ## var = { .rc_name = STR_NOCAST((_rc_name)) }
#define INCBIN_GET(var) _incbin_get(&_incbin_ ## var)

enum _incbin_state {
    INCBIN_STATE_UNSEARCHED,
    INCBIN_STATE_SEARCHING,
    INCBIN_STATE_SEARCHED
};

struct _incbin_rc_resource {
    struct atomic_i32 state;
    struct string rc_name;
    struct buffer data;
};

struct buffer _incbin_get(struct _incbin_rc_resource *inc);

#else


/* ========================== *
 * Clang incbin
 * ========================== */

#define INCBINSTR2(x) #x
#define INCBINSTR(x) INCBINSTR2(x)

#if PLATFORM_WINDOWS
# define INCBIN_SECTION ".rdata, \"dr\""
#elif PLATFORM_MAC
# define INCBIN_SECTION "__TEXT,__const"
#else
# define INCBIN_SECTION ".rodata"
#endif

/* Includes raw binary data into the executable. */
/* https://gist.github.com/mmozeiko/ed9655cf50341553d282 */
#define INCBIN_INCLUDE(var, filename) \
    __asm__(".section " INCBIN_SECTION "\n" \
            ".global _incbin_" INCBINSTR(var) "_start\n" \
            ".balign 16\n" \
            "_incbin_" INCBINSTR(var) "_start:\n" \
            ".incbin \"" filename "\"\n" \
            \
            ".global _incbin_" INCBINSTR(var) "_end\n" \
            ".balign 1\n" \
            "_incbin_" INCBINSTR(var) "_end:\n" \
    ); \
    extern __attribute((aligned(16))) const char _incbin_ ## var ## _start[]; \
    extern                            const char _incbin_ ## var ## _end[]

/* Retrieve a buffer for included data using the variable supplied to INCBIN_INCLUDE */
#define INCBIN_GET(var) BUFFER_FROM_POINTERS(_incbin_ ## var ## _start, _incbin_ ## var ## _end)

#endif

#endif
