#include <string.h>
#include <stdarg.h>
#include <stdio.h>

#include "vn_result.h"
#include "vn_malloc.h"


static char *vform(const char* format, va_list args) 
{
    size_t size = 1024;
    char* buffer = (char*)vn_malloc(size, NULL);

    while (1) 
    {
        int n = vsnprintf(buffer, size, format, args);
        
        // If that worked, return a string.
        if ((n > -1) && (static_cast<size_t>(n) < size)) {
            return buffer;
        }
        
        // Else try again with more space.
        size = (n > -1) ?
            n + 1 :   // ISO/IEC 9899:1999
            size * 2; // twice the old size

        vn_free(buffer);
        buffer = (char*)vn_malloc(size, NULL);
    }
}

vn_result_t *vn_result_create(int error_code, const char *error_string)
{
    vn_result_t *r = (vn_result_t *)vn_malloc(sizeof(vn_result_t), NULL);

    r->error_code   = error_code;

    if (error_string)
    {
        r->error_string = (char*)vn_malloc(strlen(error_string) + 1, NULL);
        strcpy(r->error_string, error_string);
    }
    else
    {
        r->error_string = (char*)vn_malloc(1, NULL);
    }

    return r;
}

void vn_result_destroy(vn_result_t *r)
{
    if (r->error_string)
        vn_free(r->error_string);

    if (r->kvl)
        vn_kv_list_destroy(r->kvl);

    vn_free(r);
}

void vn_result_set_error(vn_result_t *r, int error_code, const char *error_fmt, ...)
{
    va_list va;                                                                                                                                        
    va_start(va, error_fmt);
    
    r->error_code = error_code;

    if (r->error_string)
        vn_free(r->error_string);

    r->error_string = vform(error_fmt, va);

    va_end(va);
}
