gnucash/libgnucash/backend/xml/gnc-commodity-xml-v2.cpp
John Ralls bbb4113a5a Bug 798156 - glib 2.68.0 breaks gnucash
Move all of the #include <glib> to before the extern "C" blocks
so that the include guards will protect against headers inside
the extern "C" block also including glib.h.
2021-04-20 11:03:23 -07:00

305 lines
9.3 KiB
C++

/********************************************************************\
* gnc-commodity-xml-v2.c -- commodity xml i/o implementation *
* *
* Copyright (C) 2001 James LewisMoss <dres@debian.org> *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License*
* along with this program; if not, contact: *
* *
* Free Software Foundation Voice: +1-617-542-5942 *
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
* Boston, MA 02110-1301, USA gnu@gnu.org *
* *
\********************************************************************/
#include <glib.h>
extern "C"
{
#include <config.h>
#include <string.h>
#include "AccountP.h"
#include "Account.h"
}
#include "gnc-xml-helper.h"
#include "sixtp.h"
#include "sixtp-utils.h"
#include "sixtp-parsers.h"
#include "sixtp-utils.h"
#include "sixtp-dom-parsers.h"
#include "sixtp-dom-generators.h"
#include "gnc-xml.h"
#include "io-gncxml-gen.h"
static QofLogModule log_module = GNC_MOD_IO;
const gchar* commodity_version_string = "2.0.0";
/* ids */
#define gnc_commodity_string "gnc:commodity"
#define cmdty_namespace "cmdty:space"
#define cmdty_id "cmdty:id"
#define cmdty_name "cmdty:name"
#define cmdty_xcode "cmdty:xcode"
#define cmdty_fraction "cmdty:fraction"
#define cmdty_get_quotes "cmdty:get_quotes"
#define cmdty_quote_source "cmdty:quote_source"
#define cmdty_quote_tz "cmdty:quote_tz"
#define cmdty_slots "cmdty:slots"
xmlNodePtr
gnc_commodity_dom_tree_create (const gnc_commodity* com)
{
gnc_quote_source* source;
const char* string;
xmlNodePtr ret;
gboolean currency = gnc_commodity_is_iso (com);
xmlNodePtr slotsnode =
qof_instance_slots_to_dom_tree (cmdty_slots, QOF_INSTANCE (com));
if (currency && !gnc_commodity_get_quote_flag (com) && !slotsnode)
return NULL;
ret = xmlNewNode (NULL, BAD_CAST gnc_commodity_string);
xmlSetProp (ret, BAD_CAST "version", BAD_CAST commodity_version_string);
xmlAddChild (ret, text_to_dom_tree (cmdty_namespace,
gnc_commodity_get_namespace (com)));
xmlAddChild (ret, text_to_dom_tree (cmdty_id,
gnc_commodity_get_mnemonic (com)));
if (!currency)
{
if (gnc_commodity_get_fullname (com))
{
xmlAddChild (ret, text_to_dom_tree (cmdty_name,
gnc_commodity_get_fullname (com)));
}
if (gnc_commodity_get_cusip (com) &&
strlen (gnc_commodity_get_cusip (com)) > 0)
{
xmlAddChild (ret, text_to_dom_tree (
cmdty_xcode,
gnc_commodity_get_cusip (com)));
}
xmlAddChild (ret, int_to_dom_tree (cmdty_fraction,
gnc_commodity_get_fraction (com)));
}
if (gnc_commodity_get_quote_flag (com))
{
xmlNewChild (ret, NULL, BAD_CAST cmdty_get_quotes, NULL);
source = gnc_commodity_get_quote_source (com);
if (source)
xmlAddChild (ret, text_to_dom_tree (cmdty_quote_source,
gnc_quote_source_get_internal_name (source)));
string = gnc_commodity_get_quote_tz (com);
if (string)
xmlAddChild (ret, text_to_dom_tree (cmdty_quote_tz, string));
}
if (slotsnode)
xmlAddChild (ret, slotsnode);
return ret;
}
/***********************************************************************/
struct com_char_handler
{
const char* tag;
void (*func) (gnc_commodity* com, const char* val);
};
struct com_char_handler com_handlers[] =
{
{ cmdty_namespace, gnc_commodity_set_namespace },
{ cmdty_id, gnc_commodity_set_mnemonic },
{ cmdty_name, gnc_commodity_set_fullname },
{ cmdty_xcode, gnc_commodity_set_cusip },
{ cmdty_quote_tz, gnc_commodity_set_quote_tz },
{ 0, 0 }
};
static void
set_commodity_value (xmlNodePtr node, gnc_commodity* com)
{
if (g_strcmp0 ((char*) node->name, cmdty_fraction) == 0)
{
gint64 val;
char* string;
string = (char*) xmlNodeGetContent (node->xmlChildrenNode);
if (string_to_gint64 (string, &val))
{
gnc_commodity_set_fraction (com, val);
}
xmlFree (string);
}
else if (g_strcmp0 ((char*)node->name, cmdty_get_quotes) == 0)
{
gnc_commodity_set_quote_flag (com, TRUE);
}
else if (g_strcmp0 ((char*)node->name, cmdty_quote_source) == 0)
{
gnc_quote_source* source;
char* string;
string = (char*) xmlNodeGetContent (node->xmlChildrenNode);
source = gnc_quote_source_lookup_by_internal (string);
if (!source)
source = gnc_quote_source_add_new (string, FALSE);
gnc_commodity_set_quote_source (com, source);
xmlFree (string);
}
else if (g_strcmp0 ((char*)node->name, cmdty_slots) == 0)
{
/* We ignore the results here */
dom_tree_create_instance_slots (node, QOF_INSTANCE (com));
}
else
{
struct com_char_handler* mark;
for (mark = com_handlers; mark->tag; mark++)
{
if (g_strcmp0 (mark->tag, (char*)node->name) == 0)
{
gchar* val = dom_tree_to_text (node);
g_strstrip (val);
(mark->func) (com, val);
g_free (val);
break;
}
}
}
}
static gboolean
valid_commodity (gnc_commodity* com)
{
if (gnc_commodity_get_namespace (com) == NULL)
{
PWARN ("Invalid commodity: no namespace");
return FALSE;
}
if (gnc_commodity_get_mnemonic (com) == NULL)
{
PWARN ("Invalid commodity: no mnemonic");
return FALSE;
}
if (gnc_commodity_get_fraction (com) == 0)
{
PWARN ("Invalid commodity: 0 fraction");
return FALSE;
}
return TRUE;
}
static gnc_commodity*
gnc_commodity_find_currency (QofBook* book, xmlNodePtr tree)
{
gnc_commodity_table* table;
gnc_commodity* currency = NULL;
gchar* exchange = NULL, *mnemonic = NULL;
xmlNodePtr node;
for (node = tree->xmlChildrenNode; node; node = node->next)
{
if (g_strcmp0 ((char*) node->name, cmdty_namespace) == 0)
exchange = (gchar*) xmlNodeGetContent (node->xmlChildrenNode);
if (g_strcmp0 ((char*) node->name, cmdty_id) == 0)
mnemonic = (gchar*) xmlNodeGetContent (node->xmlChildrenNode);
}
if (exchange
&& gnc_commodity_namespace_is_iso (exchange)
&& mnemonic)
{
table = gnc_commodity_table_get_table (book);
currency = gnc_commodity_table_lookup (table, exchange, mnemonic);
}
if (exchange)
xmlFree (exchange);
if (mnemonic)
xmlFree (mnemonic);
return currency;
}
static gboolean
gnc_commodity_end_handler (gpointer data_for_children,
GSList* data_from_children, GSList* sibling_data,
gpointer parent_data, gpointer global_data,
gpointer* result, const gchar* tag)
{
gnc_commodity* com, *old_com;
xmlNodePtr achild;
xmlNodePtr tree = (xmlNodePtr)data_for_children;
gxpf_data* gdata = (gxpf_data*)global_data;
QofBook* book = static_cast<decltype (book)> (gdata->bookdata);
if (parent_data)
{
return TRUE;
}
/* OK. For some messed up reason this is getting called again with a
NULL tag. So we ignore those cases */
if (!tag)
{
return TRUE;
}
g_return_val_if_fail (tree, FALSE);
com = gnc_commodity_new (book, NULL, NULL, NULL, NULL, 0);
old_com = gnc_commodity_find_currency (book, tree);
if (old_com)
gnc_commodity_copy (com, old_com);
for (achild = tree->xmlChildrenNode; achild; achild = achild->next)
{
set_commodity_value (achild, com);
}
if (!valid_commodity (com))
{
PWARN ("Invalid commodity parsed");
xmlElemDump (stdout, NULL, tree);
printf ("\n");
fflush (stdout);
gnc_commodity_destroy (com);
return FALSE;
}
gdata->cb (tag, gdata->parsedata, com);
xmlFreeNode (tree);
return TRUE;
}
sixtp*
gnc_commodity_sixtp_parser_create (void)
{
return sixtp_dom_parser_new (gnc_commodity_end_handler, NULL, NULL);
}