summaryrefslogtreecommitdiff
path: root/src/currency.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/currency.c')
-rw-r--r--src/currency.c300
1 files changed, 60 insertions, 240 deletions
diff --git a/src/currency.c b/src/currency.c
index 2add81b..ea81761 100644
--- a/src/currency.c
+++ b/src/currency.c
@@ -1,276 +1,96 @@
-#include <time.h>
+/*
+ * Copyright (C) 2008-2011 Robert Ancell.
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation, either version 2 of the License, or (at your option) any later
+ * version. See http://www.gnu.org/copyleft/gpl.html the full text of the
+ * license.
+ */
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <gio/gio.h>
-#include <libxml/tree.h>
-#include <libxml/xpath.h>
-#include <libxml/xpathInternals.h>
+#include <string.h>
+#include <stdarg.h>
#include "currency.h"
-#include "mp.h"
-
-typedef struct {
- char* short_name;
- MPNumber value;
-} currency;
-
-static currency* currencies = NULL;
-static int currency_count = 0;
-
-static gboolean downloading_rates = FALSE;
-static gboolean loaded_rates = FALSE;
-
-static char* get_rate_filepath()
-{
- return g_build_filename(g_get_user_cache_dir(), "mate-calc", "eurofxref-daily.xml", NULL);
-}
+#include "mp-serializer.h"
+#include "currency-manager.h" // FIXME: Move out of here
-static int currency_get_index(const char *short_name)
+struct CurrencyPrivate
{
- int i;
+ gchar *name;
+ gchar *display_name;
+ gchar *symbol;
+ MPNumber value;
+};
- for (i = 0; i < currency_count; i++)
- {
- if (!strcmp(short_name, currencies[i].short_name))
- {
- if (mp_is_negative(&currencies[i].value) || mp_is_zero(&currencies[i].value))
- {
- return -1;
- }
- else
- {
- return i;
- }
- }
- }
+G_DEFINE_TYPE (Currency, currency, G_TYPE_OBJECT);
- return -1;
-}
-/* A file needs to be redownloaded if it doesn't exist, or every 7 days.
- * When an error occur, it probably won't hurt to try to download again.
- */
-static int currency_rates_needs_update()
+Currency *
+currency_new(const gchar *name,
+ const gchar *display_name,
+ const gchar *symbol)
{
- gchar* filename = get_rate_filepath();
- struct stat buf;
-
- if (!g_file_test(filename, G_FILE_TEST_IS_REGULAR))
- {
- g_free(filename);
- return 1;
- }
-
- if (g_stat(filename, &buf) == -1)
- {
- g_free(filename);
- return 1;
- }
-
- g_free(filename);
+ Currency *currency = g_object_new(currency_get_type(), NULL);
- if (difftime(time(NULL), buf.st_mtime) > (60 * 60 * 24 * 7))
- {
- return 1;
- }
+ currency->priv->name = g_strdup(name);
+ currency->priv->display_name = g_strdup(display_name);
+ currency->priv->symbol = g_strdup(symbol);
- return 0;
+ return currency;
}
-static void download_cb(GObject* object, GAsyncResult* result, gpointer user_data)
+const gchar *
+currency_get_name(Currency *currency)
{
- GError* error = NULL;
-
- if (g_file_copy_finish(G_FILE(object), result, &error))
- {
- g_debug("Rates updated");
- }
- else
- {
- g_warning("Couldn't download currency file: %s", error->message);
- }
-
- g_clear_error(&error);
- downloading_rates = FALSE;
+ g_return_val_if_fail (currency != NULL, NULL);
+ return currency->priv->name;
}
-static void currency_download_rates()
+const gchar *
+currency_get_display_name(Currency *currency)
{
- gchar* filename;
- gchar* directory;
- GFile* source;
- GFile* dest;
-
- downloading_rates = TRUE;
- g_debug("Downloading rates...");
-
- filename = get_rate_filepath();
- directory = g_path_get_dirname(filename);
- g_mkdir_with_parents(directory, 0755);
- g_free(directory);
-
- /* HACK: It is safe? */
- source = g_file_new_for_uri("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml");
- dest = g_file_new_for_path(filename);
- g_free(filename);
-
- g_file_copy_async(source, dest, G_FILE_COPY_OVERWRITE, G_PRIORITY_DEFAULT, NULL, NULL, NULL, download_cb, NULL);
- g_object_unref(source);
- g_object_unref(dest);
+ g_return_val_if_fail (currency != NULL, NULL);
+ return currency->priv->display_name;
}
-static void set_rate(xmlNodePtr node, currency* cur)
+const gchar *
+currency_get_symbol(Currency *currency)
{
- xmlAttrPtr attribute;
-
- for (attribute = node->properties; attribute; attribute = attribute->next)
- {
- if (strcmp((char*) attribute->name, "currency") == 0)
- {
- cur->short_name = (char*) xmlNodeGetContent((xmlNodePtr) attribute);
- }
- else if (strcmp ((char*) attribute->name, "rate") == 0)
- {
- char* val = (char*) xmlNodeGetContent((xmlNodePtr) attribute);
- mp_set_from_string(val, 10, &(cur->value));
- xmlFree(val);
- }
- }
+ g_return_val_if_fail (currency != NULL, NULL);
+ return currency->priv->symbol;
}
-static void currency_load_rates()
-{
- char* filename = get_rate_filepath();
- xmlDocPtr document;
- xmlXPathContextPtr xpath_ctx;
- xmlXPathObjectPtr xpath_obj;
- int i;
- int len;
-
- g_return_if_fail(g_file_test(filename, G_FILE_TEST_IS_REGULAR));
-
- xmlInitParser();
- document = xmlReadFile(filename, NULL, 0);
- g_free (filename);
-
- if (document == NULL)
- {
- fprintf(stderr, "Couldn't parse data file\n");
- return;
- }
- xpath_ctx = xmlXPathNewContext(document);
-
- if (xpath_ctx == NULL)
- {
- xmlFreeDoc(document);
- fprintf(stderr, "Couldn't create XPath context\n");
- return;
- }
-
- xmlXPathRegisterNs(xpath_ctx, BAD_CAST("xref"), BAD_CAST("http://www.ecb.int/vocabulary/2002-08-01/eurofxref"));
- xpath_obj = xmlXPathEvalExpression(BAD_CAST("//xref:Cube[@currency][@rate]"), xpath_ctx);
-
- if (xpath_obj == NULL)
- {
- xmlXPathFreeContext(xpath_ctx);
- xmlFreeDoc(document);
- fprintf(stderr, "Couldn't create XPath object\n");
- return;
- }
-
- len = (xpath_obj->nodesetval) ? xpath_obj->nodesetval->nodeNr : 0;
- currency_count = len + 1;
- currencies = g_slice_alloc0(sizeof(currency) * currency_count);
-
- for (i = 0; i < len; i++)
- {
- if (xpath_obj->nodesetval->nodeTab[i]->type == XML_ELEMENT_NODE)
- {
- set_rate(xpath_obj->nodesetval->nodeTab[i], &currencies[i]);
- }
-
- // Avoid accessing removed elements
- if (xpath_obj->nodesetval->nodeTab[i]->type != XML_NAMESPACE_DECL)
- {
- xpath_obj->nodesetval->nodeTab[i] = NULL;
- }
- }
-
- currencies[len].short_name = g_strdup("EUR");
- MPNumber foo;
- mp_set_from_integer(1, &foo);
- currencies[len].value = foo;
-
- xmlXPathFreeObject(xpath_obj);
- xmlXPathFreeContext(xpath_ctx);
- xmlFreeDoc(document);
- xmlCleanupParser();
-
- g_debug("Rates loaded");
- loaded_rates = TRUE;
+void
+currency_set_value(Currency *currency, MPNumber *value)
+{
+ g_return_if_fail (currency != NULL);
+ g_return_if_fail (value != NULL);
+ mp_set_from_mp (value, &currency->priv->value);
}
-gboolean currency_convert(const MPNumber* from_amount, const char* source_currency, const char* target_currency, MPNumber* to_amount)
+const MPNumber *
+currency_get_value(Currency *currency)
{
- int from_index, to_index;
-
- if (downloading_rates)
- {
- return FALSE;
- }
-
- /* Update currency if necessary */
- if (currency_rates_needs_update())
- {
- currency_download_rates();
- return FALSE;
- }
-
- if (!loaded_rates)
- {
- currency_load_rates();
- }
-
- from_index = currency_get_index(source_currency);
- to_index = currency_get_index(target_currency);
-
- if (from_index < 0 || to_index < 0)
- {
- return FALSE;
- }
-
- if (mp_is_zero(&currencies[from_index].value) || mp_is_zero(&currencies[to_index].value))
- {
- mp_set_from_integer(0, to_amount);
- return FALSE;
- }
-
- mp_divide(from_amount, &currencies[from_index].value, to_amount);
- mp_multiply(to_amount, &currencies[to_index].value, to_amount);
-
- return TRUE;
+ g_return_val_if_fail (currency != NULL, NULL);
+ return &currency->priv->value;
}
-void currency_free_resources()
-{
- int i;
- for (i = 0; i < currency_count; i++)
- {
- if (currencies[i].short_name != NULL)
- {
- xmlFree(currencies[i].short_name);
- }
- }
+static void
+currency_class_init(CurrencyClass *klass)
+{
+ g_type_class_add_private(klass, sizeof(CurrencyPrivate));
+}
- g_slice_free1(currency_count * sizeof(currency), currencies);
- currencies = NULL;
- currency_count = 0;
+static void
+currency_init(Currency *currency)
+{
+ currency->priv = G_TYPE_INSTANCE_GET_PRIVATE(currency, currency_get_type(), CurrencyPrivate);
}