/lib/perl/Blerg-Database/Database.xs
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include "ppport.h"

#include "config.h"
#include "database/database.h"
#include "database/blergref.h"
#include "database/tags.h"
#include "database/subscription.h"
#include "database/util.h"
#include "database/configuration.h"
#include "common/auth.h"

#include "const-c.inc"

HV * blergref_to_perl_hash(struct blergref *list) {
        HV *tmp;
        char buf[21];
        int n;

        tmp = newHV();
        hv_store(tmp, "author", 6, newSVpv(list->author, 0), 0);
        n = snprintf(buf, 21, "%llu", list->record);
        hv_store(tmp, "record", 6, newSVpv(buf, n), 0);

        return tmp;
}

MODULE = Blerg::Database		PACKAGE = Blerg::Database		

INCLUDE: const-xs.inc
PROTOTYPES: ENABLE

int init()
    CODE:
        RETVAL = blerg_init();
    OUTPUT:
        RETVAL

int exists(const char *name)
    CODE:
        RETVAL = blerg_exists(name);
    OUTPUT:
        RETVAL

struct blerg * _open(const char *name)
    CODE:
        RETVAL = blerg_open(name);
    OUTPUT:
        RETVAL

int _close(struct blerg *ptr)
    CODE:
        RETVAL = blerg_close(ptr);
    OUTPUT:
        RETVAL

const char * _store(struct blerg *ptr, const char *data, int length(data))
    PROTOTYPE: $$
    INIT:
        uint64_t record;
        char buf[21];
        int n;
    PPCODE:
        record = blerg_store(ptr, data, XSauto_length_of_data);
        n = snprintf(buf, 21, "%llu", record);
        XPUSHs(sv_2mortal(newSVpv(buf, n)));

const char * _fetch(struct blerg *ptr, const char *str_record)
    INIT:
        uint64_t record;
        char *buf;
        int buflen;
        int n;
    PPCODE:
        record = strtoull(str_record, NULL, 0);
        n = blerg_fetch(ptr, record, &buf, &buflen);
        if (!n) {
            XSRETURN_UNDEF;
        }
        XPUSHs(sv_2mortal(newSVpvn(buf, buflen)));
        free(buf);

const char * _get_record_count(struct blerg *ptr)
    INIT:
        uint64_t count;
        char buf[21];
        int n;
    PPCODE:
        count = blerg_get_record_count(ptr);
        n = snprintf(buf, 21, "%llu", count);
        XPUSHs(sv_2mortal(newSVpv(buf, n)));

time_t _get_timestamp(struct blerg *ptr, const char *str_record)
    INIT:
        uint64_t record;
    CODE:
        record = strtoull(str_record, NULL, 0);
        RETVAL = blerg_get_timestamp(ptr, record);
    OUTPUT:
        RETVAL

int _set_subscription_mark(struct blerg *ptr)
    CODE:
        RETVAL = blerg_set_subscription_mark(ptr);
    OUTPUT:
        RETVAL

const char * _get_subscription_mark(struct blerg *ptr)
    INIT:
        uint64_t mark;
        char buf[21];
        int n;
    PPCODE:
        mark = blerg_get_subscription_mark(ptr);
        n = snprintf(buf, 21, "%llu", mark);
        XPUSHs(sv_2mortal(newSVpv(buf, n)));

int _set_status(struct blerg *ptr, int status, int v)
    CODE:
        RETVAL = blerg_set_status(ptr, status, v);
    OUTPUT:
        RETVAL

int _get_status(struct blerg *ptr, int status)
    CODE:
        RETVAL = blerg_get_status(ptr, status);
    OUTPUT:
        RETVAL

void tag_list(const char *tag, const char *str_offset, int direction)
    INIT:
        HV * tmp;
        struct blergref *list;
        uint64_t offset;
        int count, i;
    PPCODE:
        offset = strtoull(str_offset, NULL, 0);
        count = 50;
        list = tag_list(tag, offset, &count, direction);
        if (list == NULL) {
            XSRETURN_EMPTY;
        }

        i = count - 1;
        while (i >= 0) {
            tmp = blergref_to_perl_hash(&list[i]);
            XPUSHs(sv_2mortal(newRV_noinc((SV*)tmp)));
            i--;
        }
        free(list);

int subscription_add(const char *from, const char *to)

int subscription_remove(const char *from, const char *to)

void _subscription_list(const char *author, const char *str_offset, int direction)
    INIT:
        HV *tmp;
        struct blergref *list;
        uint64_t offset;
        int count, i;
    PPCODE:
        offset = strtoull(str_offset, NULL, 0);
        count = 50;
        list = subscription_list(author, offset, &count, direction);
        if (list == NULL) {
            XSRETURN_EMPTY;
        }

        i = count - 1;
        while (i >= 0) {
            tmp = blergref_to_perl_hash(&list[i]);
            XPUSHs(sv_2mortal(newRV_noinc((SV*)tmp)));
            i--;
        }
        free(list);

int valid_tag_name(const char *name)

int valid_name(const char *name)

int auth_set_password(const char *username, const char *password)

int auth_check_password(const char *username, const char *password)

char * auth_login(const char *username, const char *password)
    INIT:
        char *token;
    PPCODE:
        token = auth_login(username, password);
        if (token != NULL) {
            XPUSHs(sv_2mortal(newSVpv(token, TOKEN_SIZE * 2)));
        } else {
            XSRETURN_UNDEF;
        }
        free(token);

int auth_logout(const char *username, const char *token)

int auth_check_token(const char *username, const char *given_token)

void auth_get_counter(const char *username)
    INIT:
        uint32_t counter = 0;
    PPCODE:
        if (auth_get_counter(username, &counter)) {
            XPUSHs(sv_2mortal(newSVuv(counter)));
        } else {
            XSRETURN_UNDEF;
        }

void configuration()
    INIT:
        HV *confhash;
    PPCODE:
        confhash = newHV();
        hv_store(confhash, "base_path", 9, newSVpv(blergconf.base_path, 0), 0);
        hv_store(confhash, "data_path", 9, newSVpv(blergconf.data_path, 0), 0);
        hv_store(confhash, "hash_tags_path", 14, newSVpv(blergconf.hash_tags_path, 0), 0);
        hv_store(confhash, "ref_tags_path", 13, newSVpv(blergconf.ref_tags_path, 0), 0);

        XPUSHs(sv_2mortal(newRV_noinc((SV*)confhash)));