
#ifndef ZAN_RKT_H_
#define ZAN_RKT_H_

/*
 * TODO:
 * * test if this actually works
 */

//#ifdef USE_ROCKET

#include <stddef.h>
#include <stdint.h>

#include "type.h"
#include "sys.h"

#include "crp_file.h"

struct rkt_state {
    struct crp_file_rkt* map;
    size_t mapsz;
};

static struct rkt_state rkt_map_file(const char* file) {
    const static struct rkt_state ret_fail = (struct rkt_state){
        .map = NULL, .mapsz = 0
    };

    int filed = SYS_open(file, O_RDWR);

    if (filed < 0) {
        return ret_fail;
    }
    struct stat st;
    SYS_fstat(filed, &st);

    void* map = SYS_mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_SHARED, filed, 0);
    if (!map || !~map) {
        SYS_close(filed);
        return ret_fail;
    }

    return (struct rkt_state){
        .map   = map,
        .mapsz = (size_t)st.st_size
    };
}

static void rkt_unmap_file(struct rkt_state st) {
    SYS_munmap(st.map, st.mapsz);
}

static uint32_t str_hash_djb2(const char* name) {
    uint32_t r = 5381;

    for (; *name; ++name) {
        r = ((r << 5) + r) ^ (uint32_t)*name;
    }

    return r;
}

static double rkt_get_value(struct rkt_state st, const char* name) {
    uint32_t nhash = str_hash_djb2(name);

    const char* nameptr = (const char*)&st.map->vars
        + sizeof(double) * st.map->num_vars;
    for (uint64_t i = 0; i < st.map->num_vars; ++i) {
        uint32_t r = 5381;

        for (; *nameptr; ++nameptr) {
            r = ((r << 5) + r) ^ (uint32_t)*nameptr;
        }

        ++nameptr; // skip nullterm

        if (r == nhash) {
            return st.map->vars[i];
        }
    }

    return 0.0 / 0.0; // NaN
}

//#endif

#endif

