Newer
Older
xmpp-bot / src / expenses / types.c
/* function definition to parse a string instead of a file
 */
#include <stdio.h>
#include <stdbool.h>
#include <unistd.h>
#include <time.h>
#include <glib.h>
#include "types.h"

extern BotCommand g_LastCommand = BOT_CMD_NONE;
extern BotExpenseEntry *g_LastExpenseEntry = NULL;
extern BotReminder *g_LastReminder = NULL;
extern GString *g_filename = NULL;

BotCommand bot_get_last_command()
{
    return g_LastCommand;
}
void bot_set_last_command(BotCommand cmd)
{
    g_LastCommand = cmd;
}

BotExpenseEntry *bot_get_last_expense()
{
    return g_LastExpenseEntry;
}
void bot_set_last_expense(BotExpenseEntry *entry)
{
    if(g_LastExpenseEntry) {
        free_bot_expense_entry(g_LastExpenseEntry);
    }
    g_LastExpenseEntry = entry;
}

BotReminder *bot_get_last_reminder()
{
    return g_LastReminder;
}
void bot_set_last_reminder(BotReminder *reminder)
{
    if(g_LastReminder) {
        free_bot_reminder(g_LastReminder);
    }
    g_LastReminder = reminder;
}

GString *bot_get_filename()
{
    return g_filename;
}

void bot_set_filename(GString *fn)
{
    if(g_filename) {
        g_string_free(g_filename, true);
    }
    g_filename = fn;
}

/* Create a BotExpenseEntry with data fed from the parser.
 * Returns NULL if error getting local time.
 */
BotExpenseEntry *create_bot_expense_entry
(
 const BotExpenseEntry *previous,
 const unsigned int id,
 const BotCommand cmd,
 const double value,
 GString* user,
 GString* notes
)
{
    double signedValue = value;
    BotExpenseEntry *entry = malloc(sizeof *entry); // TODO this should be freed once it's written to registry
    struct tm *lt = malloc(sizeof *lt);
    time_t t = time(NULL);

    /* get the local time */
    localtime_r(&t, lt);
    if(lt == NULL) {
        fprintf(stderr, "Unable to get localtime.\n");
        return NULL;
    }

    if(cmd == BOT_CMD_OUT) {
        signedValue = -value;
    }

    entry->id = id;
    entry->time = *lt;
    entry->value = signedValue;
    entry->user = user;
    entry->notes = notes;
    entry->_serialized = false;

    return entry;
}

/* FP should not be null. This assumes that it has been initialized with an header line as well
 * Returns NULL in case 'entry' is uninitialized.
 */
GString *serialize_bot_expense_entry_csv
(
 BotExpenseEntry *entry
)
{
    /* will be automatically expanded by g_string_printf */
    GString *tstr = g_string_new(NULL);
    GString *result = g_string_new(NULL);

    if(entry == NULL) {
        fprintf(stderr, "BotExpenseEntry 'entry' is NULL. Initialize it before calling 'serialize_bot_expense_entry_csv'\n");
        return NULL;
    }

    /* Time in ISO 8061 */
    g_string_printf(tstr,
                    "%d-%02d-%02d %02d:%02d:%02d",
                    entry->time.tm_year + 1900,
                    entry->time.tm_mon + 1,
                    entry->time.tm_mday,
                    entry->time.tm_hour,
                    entry->time.tm_min,
                    entry->time.tm_sec);

    g_string_printf(result,
                    "%u,%s,%.2f,%s,%s\n",
                    entry->id,
                    tstr->str,
                    entry->value,
                    entry->user->str,
                    entry->notes->str
                    );

    entry->_serialized = true;

    return result;
}


/* To be called after it has been serialized */
void free_bot_expense_entry
(
 BotExpenseEntry *entry
)
{
    if(!entry->_serialized) {
        /* TODO could fail here instead */
        fprintf(stderr, "WARNING: freeing an entry that wasn't serialized!\n");
    }

    /* Also free underlying string, we don't need it anymore */
    g_string_free(entry->user, TRUE);
    g_string_free(entry->notes, TRUE);
    free(entry);
}

void free_bot_reminder
(
 BotReminder *reminder
)
{
    g_string_free(reminder->from, true);
    free(reminder);
}