From 5b7f9b46318f03d14a4f1e62ea42741bd23ea004 Mon Sep 17 00:00:00 2001 From: Dave Peticolas Date: Thu, 22 Feb 2001 07:29:05 +0000 Subject: [PATCH] James LewisMoss's big big patch. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@3678 57a11ea4-9604-0410-9ed3-97b8803252fd --- ChangeLog | 73 +++++++ src/doc/xml/account-v2.dtd | 1 + src/doc/xml/types.dtd | 27 +-- src/engine/Account.c | 2 +- src/engine/Account.h | 3 +- src/engine/Makefile.am | 2 + src/engine/Transaction.c | 56 ++--- src/engine/gnc-account-xml-v2.c | 70 ++++++- src/engine/gnc-book.c | 6 + src/engine/gnc-book.h | 8 + src/engine/gnc-commodity-xml-v2.c | 142 +++++++++++++ src/engine/gnc-engine.c | 19 +- src/engine/gnc-engine.h | 4 +- src/engine/gnc-transaction-xml-v2.c | 75 +++++++ src/engine/gnc-xml.h | 25 +++ src/engine/kvp_frame.c | 249 ++++++++++++++++++---- src/engine/kvp_frame.h | 16 +- src/engine/sixtp-dom-generators.c | 135 +++++++++++- src/engine/sixtp-dom-generators.h | 6 +- src/engine/sixtp-dom-parsers.c | 314 +++++++++++++++++++++++++++- src/engine/sixtp-dom-parsers.h | 15 +- src/engine/sixtp-to-dom-parser.c | 23 +- src/register/QuickFill.c | 2 +- 23 files changed, 1147 insertions(+), 126 deletions(-) create mode 100644 src/engine/gnc-commodity-xml-v2.c create mode 100644 src/engine/gnc-transaction-xml-v2.c create mode 100644 src/engine/gnc-xml.h diff --git a/ChangeLog b/ChangeLog index 9d634d269f..e0c1f559bb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,76 @@ +2001-02-22 James LewisMoss + + * src/test/test-dom-parser1.c: Move generic funcs to test-stuff.c + + * src/test/test-dom-converters1.c: Move generic funcs to + test-stuff.c + + * src/test/test-date-converting.c: move generic funcs to + test-stuff.c + + * src/engine/sixtp-to-dom-parser.c (dom_start_handler): cast arg + to xmlNewChild to xmlNodePtr + (dom_chars_handler): Remove is_whitespace func and use isspace_str + from other file. + + * src/engine/sixtp-dom-parsers.c: Add all the dom_tree_to funcs. + + * src/engine/sixtp-dom-generators.c (guid_to_dom_tree): Make GUID + arg const. + (commodity_ref_to_dom_tree): check nulls. + (add_kvp_value_node): Add all the kvp code. + + * src/engine/kvp_frame.c: Use string cache func. + (charstar_va_list_to_gslist): new func. + (kvp_frame_get_frame): More refactoring. + + * src/engine/gnc-engine.h: Add func def as below. + + * src/engine/gnc-engine.c: Move string cache creation to function + to get so that you don't have to gnc_engine_init to use the global + string cache. + (gnc_engine_get_string_cache): Add func as above. + + * src/engine/gnc-book.h: Add func as below. + + * src/engine/gnc-book.c (gnc_book_get_commodity_table): Add + function. + + * src/engine/gnc-account-xml-v2.c (gnc_account_dom_tree_create): + Complete func. + (gnc_account_end_handler): Fix up. Finish work. + + * src/engine/Transaction.c (xaccInitSplit): Use func to get string + cache rather than accessing the var directly. + + * src/engine/Account.h: same as Account.c. Add comment on + xaccAccountSet{Currency,Security} that they take control of the + gnc_commodity args. + + * src/engine/Account.c: Rename xaccAccountSetSlots to *_nc so we + use the kvp_frame provided rather than copy. + + * src/doc/xml/types.dtd: Fix up kvp type list. clean up timestamp + tuff. Simplify a bit. + + * src/doc/xml/account-v2.dtd: add code and description. + +2001-02-19 James LewisMoss + + * src/engine/kvp_frame.c: Fix < to be > in binary datasize + argument (bug fix). Add comment about appropriateness of + comparing data sizes first. + Fix double compare. was using just gint64 compare. Extracted out + double compare into double_compare function. + Fix return value of kvp_value_compare from gboolean -> gint. + Fix bug in kvp_glist_compare where it should have read (!lp2 && + lp1) and it read (!lp2) so glists never compared equal. + (kvp_frame_get_hash): Add func. + (kvp_frame_to_string): Add func. + (kvp_value_to_string): Add func. + (kvp_value_glist_to_string): Add func. + (binary_to_string): Add func. + 2001-02-15 Bill Gribble * src/scm/qif-import/qif-guess-map.scm: add stock hash diff --git a/src/doc/xml/account-v2.dtd b/src/doc/xml/account-v2.dtd index 13c7410ae0..df753dda5b 100644 --- a/src/doc/xml/account-v2.dtd +++ b/src/doc/xml/account-v2.dtd @@ -2,6 +2,7 @@ %types; diff --git a/src/doc/xml/types.dtd b/src/doc/xml/types.dtd index 1d04229905..be3a3de702 100644 --- a/src/doc/xml/types.dtd +++ b/src/doc/xml/types.dtd @@ -7,20 +7,23 @@ - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/src/engine/Account.c b/src/engine/Account.c index 205b72d70a..086b966dd0 100644 --- a/src/engine/Account.c +++ b/src/engine/Account.c @@ -460,7 +460,7 @@ xaccAccountGetSlots(Account * account) { } void -xaccAccountSetSlots(Account *account, kvp_frame *frame) +xaccAccountSetSlots_nc(Account *account, kvp_frame *frame) { if (!account) return; if (frame == account->kvp_data) return; diff --git a/src/engine/Account.h b/src/engine/Account.h index ffa07fc283..2a3f10e678 100644 --- a/src/engine/Account.h +++ b/src/engine/Account.h @@ -134,7 +134,7 @@ void xaccAccountCommitEdit (Account *account); void xaccAccountDestroy (Account *account); kvp_frame * xaccAccountGetSlots (Account *account); -void xaccAccountSetSlots(Account *account, kvp_frame *frame); +void xaccAccountSetSlots_nc(Account *account, kvp_frame *frame); /* * The xaccAccountGetGUID() subroutine will return the @@ -218,6 +218,7 @@ void xaccAccountSetCommodity (Account *account, const gnc_commodity *comm); * The future API will associate only one thing with an account: * the 'commodity'. Use xaccAccountGetCommodity() to fetch it. */ +/* these two funcs take control of thier gnc_commodity args. Don't free */ void xaccAccountSetCurrency (Account *account, const gnc_commodity *currency); void xaccAccountSetSecurity (Account *account, const gnc_commodity *security); void xaccAccountSetCurrencySCU (Account *account, int frac); diff --git a/src/engine/Makefile.am b/src/engine/Makefile.am index d7ceeb6304..7d43cec94b 100644 --- a/src/engine/Makefile.am +++ b/src/engine/Makefile.am @@ -21,6 +21,7 @@ libgncengine_la_SOURCES = \ date.c \ GNCId.c \ gnc-account-xml-v2.c \ + gnc-commodity-xml-v2.c \ guid.c \ io-gncbin-r.c \ io-gncxml-r.c \ @@ -83,6 +84,7 @@ noinst_HEADERS = \ gnc-event-p.h \ gnc-numeric.h \ gnc-xml-helper.h \ + gnc-xml.h \ sixtp-dom-generators.h \ sixtp-dom-parsers.h \ sixtp-parsers.h \ diff --git a/src/engine/Transaction.c b/src/engine/Transaction.c index 1d73c510ab..a15231f5af 100644 --- a/src/engine/Transaction.c +++ b/src/engine/Transaction.c @@ -94,8 +94,8 @@ xaccInitSplit(Split * split) split->acc = NULL; split->parent = NULL; - split->action = g_cache_insert(gnc_string_cache, ""); - split->memo = g_cache_insert(gnc_string_cache, ""); + split->action = g_cache_insert(gnc_engine_get_string_cache(), ""); + split->memo = g_cache_insert(gnc_engine_get_string_cache(), ""); split->reconciled = NREC; split->damount = gnc_numeric_zero(); split->value = gnc_numeric_zero(); @@ -147,8 +147,8 @@ xaccCloneSplit (Split *s) split->acc = s->acc; split->parent = s->parent; - split->memo = g_cache_insert (gnc_string_cache, s->memo); - split->action = g_cache_insert (gnc_string_cache, s->action); + split->memo = g_cache_insert (gnc_engine_get_string_cache(), s->memo); + split->action = g_cache_insert (gnc_engine_get_string_cache(), s->action); split->kvp_data = kvp_frame_copy (s->kvp_data); @@ -180,8 +180,8 @@ xaccFreeSplit (Split *split) kvp_frame_delete (split->kvp_data); - g_cache_remove(gnc_string_cache, split->memo); - g_cache_remove(gnc_string_cache, split->action); + g_cache_remove(gnc_engine_get_string_cache(), split->memo); + g_cache_remove(gnc_engine_get_string_cache(), split->action); /* just in case someone looks up freed memory ... */ split->memo = NULL; @@ -571,8 +571,8 @@ static void xaccInitTransaction (Transaction * trans) { /* Fill in some sane defaults */ - trans->num = g_cache_insert(gnc_string_cache, ""); - trans->description = g_cache_insert(gnc_string_cache, ""); + trans->num = g_cache_insert(gnc_engine_get_string_cache(), ""); + trans->description = g_cache_insert(gnc_engine_get_string_cache(), ""); trans->common_currency = NULL; trans->splits = NULL; @@ -626,8 +626,8 @@ xaccCloneTransaction (Transaction *t) trans = g_new0 (Transaction, 1); - trans->num = g_cache_insert (gnc_string_cache, t->num); - trans->description = g_cache_insert (gnc_string_cache, t->description); + trans->num = g_cache_insert (gnc_engine_get_string_cache(), t->num); + trans->description = g_cache_insert (gnc_engine_get_string_cache(), t->description); trans->kvp_data = kvp_frame_copy (t->kvp_data); @@ -673,8 +673,8 @@ xaccFreeTransaction (Transaction *trans) trans->splits = NULL; /* free up transaction strings */ - g_cache_remove(gnc_string_cache, trans->num); - g_cache_remove(gnc_string_cache, trans->description); + g_cache_remove(gnc_engine_get_string_cache(), trans->num); + g_cache_remove(gnc_engine_get_string_cache(), trans->description); kvp_frame_delete (trans->kvp_data); @@ -1411,13 +1411,13 @@ xaccTransRollbackEdit (Transaction *trans) * the guid would have been unlisted. Restore that */ xaccStoreEntity(trans, &trans->guid, GNC_ID_TRANS); - g_cache_remove (gnc_string_cache, trans->num); + g_cache_remove (gnc_engine_get_string_cache(), trans->num); trans->num = orig->num; - orig->num = g_cache_insert(gnc_string_cache, ""); + orig->num = g_cache_insert(gnc_engine_get_string_cache(), ""); - g_cache_remove (gnc_string_cache, trans->description); + g_cache_remove (gnc_engine_get_string_cache(), trans->description); trans->description = orig->description; - orig->description = g_cache_insert(gnc_string_cache, ""); + orig->description = g_cache_insert(gnc_engine_get_string_cache(), ""); kvp_frame_delete (trans->kvp_data); trans->kvp_data = orig->kvp_data; @@ -1466,13 +1466,13 @@ xaccTransRollbackEdit (Transaction *trans) break; } - g_cache_remove (gnc_string_cache, s->action); + g_cache_remove (gnc_engine_get_string_cache(), s->action); s->action = so->action; - so->action = g_cache_insert(gnc_string_cache, ""); + so->action = g_cache_insert(gnc_engine_get_string_cache(), ""); - g_cache_remove (gnc_string_cache, s->memo); + g_cache_remove (gnc_engine_get_string_cache(), s->memo); s->memo = so->memo; - so->memo = g_cache_insert(gnc_string_cache, ""); + so->memo = g_cache_insert(gnc_engine_get_string_cache(), ""); kvp_frame_delete (s->kvp_data); s->kvp_data = so->kvp_data; @@ -1907,8 +1907,8 @@ xaccTransSetNum (Transaction *trans, const char *xnum) if (!trans || !xnum) return; check_open (trans); - tmp = g_cache_insert(gnc_string_cache, (gpointer) xnum); - g_cache_remove(gnc_string_cache, trans->num); + tmp = g_cache_insert(gnc_engine_get_string_cache(), (gpointer) xnum); + g_cache_remove(gnc_engine_get_string_cache(), trans->num); trans->num = tmp; mark_trans (trans); } @@ -1920,8 +1920,8 @@ xaccTransSetDescription (Transaction *trans, const char *desc) if (!trans || !desc) return; check_open (trans); - tmp = g_cache_insert(gnc_string_cache, (gpointer) desc); - g_cache_remove(gnc_string_cache, trans->description); + tmp = g_cache_insert(gnc_engine_get_string_cache(), (gpointer) desc); + g_cache_remove(gnc_engine_get_string_cache(), trans->description); trans->description = tmp; mark_trans (trans); } @@ -2048,8 +2048,8 @@ xaccSplitSetMemo (Split *split, const char *memo) if (!split || !memo) return; check_open (split->parent); - tmp = g_cache_insert(gnc_string_cache, (gpointer) memo); - g_cache_remove(gnc_string_cache, split->memo); + tmp = g_cache_insert(gnc_engine_get_string_cache(), (gpointer) memo); + g_cache_remove(gnc_engine_get_string_cache(), split->memo); split->memo = tmp; mark_split (split); } @@ -2061,8 +2061,8 @@ xaccSplitSetAction (Split *split, const char *actn) if (!split || !actn) return; check_open (split->parent); - tmp = g_cache_insert(gnc_string_cache, (gpointer) actn); - g_cache_remove(gnc_string_cache, split->action); + tmp = g_cache_insert(gnc_engine_get_string_cache(), (gpointer) actn); + g_cache_remove(gnc_engine_get_string_cache(), split->action); split->action = tmp; mark_split (split); } diff --git a/src/engine/gnc-account-xml-v2.c b/src/engine/gnc-account-xml-v2.c index b3493b04c5..b69cd545eb 100644 --- a/src/engine/gnc-account-xml-v2.c +++ b/src/engine/gnc-account-xml-v2.c @@ -9,16 +9,67 @@ #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 "sixtp-dom-parsers.h" #include "AccountP.h" #include "Account.h" #include "Group.h" +const gchar *account_version_string = "2.0.0"; + xmlNodePtr gnc_account_dom_tree_create(Account *act) { - return NULL; + xmlNodePtr ret; + + ret = xmlNewNode(NULL, "gnc:account"); + xmlSetProp(ret, "version", account_version_string); + + xmlNewChild(ret, NULL, "act:name", xaccAccountGetName(act)); + + xmlAddChild(ret, guid_to_dom_tree("act:id", xaccAccountGetGUID(act))); + + xmlNewChild(ret, NULL, "act:type", + xaccAccountTypeEnumAsString(xaccAccountGetType(act))); + + xmlAddChild(ret, commodity_ref_to_dom_tree("act:currency", + xaccAccountGetCurrency(act))); + + if(xaccAccountGetCode(act)) + { + xmlNewChild(ret, NULL, "act:code", xaccAccountGetCode(act)); + } + + if(xaccAccountGetDescription(act)) + { + xmlNewChild(ret, NULL, "act:description", + xaccAccountGetDescription(act)); + } + + if(xaccAccountGetSecurity(act)) + { + xmlAddChild(ret, commodity_ref_to_dom_tree("act:security", + xaccAccountGetSecurity(act))); + } + + if(xaccAccountGetSlots(act)) + { + xmlAddChild(ret, kvp_frame_to_dom_tree("act:slots", + xaccAccountGetSlots(act))); + } + + if(xaccAccountGetParentAccount(act)) + { + xmlAddChild(ret, guid_to_dom_tree( + "act:parent", + xaccAccountGetGUID(xaccAccountGetParentAccount(act)))); + } + + return ret; } /***********************************************************************/ @@ -80,6 +131,7 @@ static gboolean account_slots_handler (xmlNodePtr node, Account* act) { /* return dom_tree_handle_kvp(act->kvp_data, node); */ + return TRUE; } static gboolean @@ -178,16 +230,19 @@ gnc_account_end_handler(gpointer data_for_children, xmlNodePtr tree = (xmlNodePtr)data_for_children; successful = TRUE; + + if(parent_data) + { + return successful; + } acc = xaccMallocAccount(); g_return_val_if_fail(acc, FALSE); xaccAccountBeginEdit(acc); - achild = tree->xmlChildrenNode; - set_handlers(account_handlers_v2); - while(!achild) + for(achild = tree->xmlChildrenNode; achild; achild = achild->next) { if(!gnc_xml_set_account_data(achild->name, achild, acc, account_handlers_v2)) @@ -195,7 +250,6 @@ gnc_account_end_handler(gpointer data_for_children, successful = FALSE; break; } - achild = achild->next; } xaccAccountCommitEdit(acc); @@ -214,17 +268,17 @@ gnc_account_end_handler(gpointer data_for_children, if(!xaccAccountGetParent(acc)) { /* FIXME: something like this */ - /* xaccGroupInsertAccount(global_data->accountgroup, acc); */ + /* xaccGroupInsertAccount(global_data, acc); */ } } - xmlFreeNode(data_for_children); + xmlFreeNode(result); return successful; } sixtp* -gnc_account_sixtp_parser_create() +gnc_account_sixtp_parser_create(void) { return sixtp_dom_parser_new(gnc_account_end_handler); } diff --git a/src/engine/gnc-book.c b/src/engine/gnc-book.c index 9a26561f3a..be96aa73cc 100644 --- a/src/engine/gnc-book.c +++ b/src/engine/gnc-book.c @@ -146,6 +146,12 @@ gnc_book_new (void) /* ============================================================== */ +gnc_commodity_table* +gnc_book_get_commodity_table(GNCBook *book) +{ + return gnc_engine_commodities(); +} + AccountGroup * gnc_book_get_group (GNCBook *book) { diff --git a/src/engine/gnc-book.h b/src/engine/gnc-book.h index 94dbb0a08f..2a36f5b3b0 100644 --- a/src/engine/gnc-book.h +++ b/src/engine/gnc-book.h @@ -124,6 +124,14 @@ GNCBackendError gnc_book_pop_error (GNCBook *book); AccountGroup * gnc_book_get_group (GNCBook *book); void gnc_book_set_group (GNCBook *book, AccountGroup *topgroup); + +/* + * gnc_book_get_commodity_table returns the commodity table associated with + * the BOOK. At the moment this just returns the global commodity table, + * but if we get everything using this we can make it a non-global table :) + */ +gnc_commodity_table* gnc_book_get_commodity_table(GNCBook *book); + /* The gnc_book_get_file_path() routine returns the fully-qualified file * path for the book. That is, if a relative or partial filename * was for the book, then it had to have been fully resolved to diff --git a/src/engine/gnc-commodity-xml-v2.c b/src/engine/gnc-commodity-xml-v2.c new file mode 100644 index 0000000000..f14ca0a925 --- /dev/null +++ b/src/engine/gnc-commodity-xml-v2.c @@ -0,0 +1,142 @@ +#include "config.h" + +#include +#include + +#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 "sixtp-dom-parsers.h" +#include "AccountP.h" +#include "Account.h" +#include "Group.h" + +const gchar *commodity_version_string = "2.0.0"; + +xmlNodePtr +gnc_commodity_dom_tree_create(const gnc_commodity *com) +{ + xmlNodePtr ret; + + ret = xmlNewNode(NULL, "gnc:commodity"); + + xmlSetProp(ret, "version", commodity_version_string); + + xmlNewChild(ret, NULL, "cmdty:space", gnc_commodity_get_namespace(com)); + xmlNewChild(ret, NULL, "cmdty:id", gnc_commodity_get_mnemonic(com)); + + if(gnc_commodity_get_fullname(com)) + { + xmlNewChild(ret, NULL, "cmdty:name", gnc_commodity_get_fullname(com)); + } + + if(gnc_commodity_get_exchange_code(com)) + { + xmlNewChild(ret, NULL, "cmdty:xcode", + gnc_commodity_get_exchange_code(com)); + } + + { + gchar *text; + text = g_strdup_printf("%d", gnc_commodity_get_fraction(com)); + xmlNewChild(ret, NULL, "cmdty:fraction", text); + g_free(text); + } + + return ret; +} + +/***********************************************************************/ + +struct com_char_handler +{ + gchar *tag; + void(*func)(gnc_commodity *com, const char*val); +}; + +struct com_char_handlers com_handlers[] = { + { "cmdty:space", gnc_commodity_set_namespace }, + { "cmdty:id", gnc_commodity_set_mnemonic }, + { "cmdty:name", gnc_commodity_set_fullname }, + { "cmdty:xcode", gnc_commodity_set_exchange_code }, + { 0, 0 } +}; + +static void +set_commodity_value(xmlNodePtr node, gnc_commodity* com) +{ + if(safe_strcmp(node->name, "cmdty:fraction")) + { + gint64 val; + if(string_to_integer(node, &val)) + { + gnc_commodity_set_fraction(com, val); + } + } + else + { + struct com_char_handlers *mark; + + for(mark = com_handlers; mark->tag; mark++) + { + if(safe_strcmp(mark->tag, node->name)) + { + gchar* val = dom_tree_to_text(node->xmlChildrenNode); + (mark->func)(com, val); + g_free(val); + break; + } + } + } +} + +static gboolean +valid_commodity(gnc_commodity *com) +{ + return TRUE; +} + +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; + xmlNodePtr achild; + xmlNodePtr tree = (xmlNodePtr)data_for_children; + + if(parent_data) + { + return TRUE; + } + + com = gnc_commodity_new(NULL, NULL, NULL, NULL, 0); + + for(achild = tree->xmlChildrenNode; achild; achild = achild->next) + { + set_commodity_value(achild, com); + } + + if(!valid_commodity(com)) + { + return FALSE; + } + + return TRUE +} + + +sixtp* +gnc_commodity_sixtp_parser_create(void) +{ + return sixtp_dom_parser_new(gnc_commodity_end_handler); +} diff --git a/src/engine/gnc-engine.c b/src/engine/gnc-engine.c index a5b7123466..08085d89a2 100644 --- a/src/engine/gnc-engine.c +++ b/src/engine/gnc-engine.c @@ -47,10 +47,8 @@ gnc_engine_init(int argc, char ** argv) { engine_is_initialized = 1; /* initialize the string cache */ - gnc_string_cache = g_cache_new( (GCacheNewFunc) g_strdup, - g_free, (GCacheDupFunc) g_strdup, g_free, g_str_hash, - g_str_hash, g_str_equal); - + gnc_engine_get_string_cache(); + xaccGUIDInit (); /* initialize the commodity table (it starts empty) */ @@ -65,6 +63,19 @@ gnc_engine_init(int argc, char ** argv) { } } +GCache* +gnc_engine_get_string_cache(void) +{ + if(!gnc_string_cache) + { + gnc_string_cache = g_cache_new( + (GCacheNewFunc) g_strdup, g_free, + (GCacheDupFunc) g_strdup, g_free, g_str_hash, + g_str_hash, g_str_equal); + } + return gnc_string_cache; +} + /******************************************************************** * gnc_engine_shutdown * shutdown backend, destroy any global data, etc. diff --git a/src/engine/gnc-engine.h b/src/engine/gnc-engine.h index 7707610c9e..da473e039b 100644 --- a/src/engine/gnc-engine.h +++ b/src/engine/gnc-engine.h @@ -61,7 +61,9 @@ gnc_commodity_table * gnc_engine_commodities(void); * Note that all the work is done when inserting or removing. Once * cached the strings are just plain C strings. */ -extern GCache *gnc_string_cache; + +/* get the gnc_string_cache. Create it if it doesn't exist already */ +GCache* gnc_engine_get_string_cache(void); #endif diff --git a/src/engine/gnc-transaction-xml-v2.c b/src/engine/gnc-transaction-xml-v2.c new file mode 100644 index 0000000000..b327280c1f --- /dev/null +++ b/src/engine/gnc-transaction-xml-v2.c @@ -0,0 +1,75 @@ +#include "config.h" + +#include +#include + +#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 "sixtp-dom-parsers.h" +#include "AccountP.h" +#include "Account.h" +#include "Group.h" + +const gchar *transaction_version_string = "2.0.0"; + +xmlNodePtr +gnc_transaction_dom_tree_create(const Transaction *com) +{ + xmlNodePtr ret; + + ret = xmlNewNode(NULL, "gnc:transaction"); + + xmlSetProp(ret, "version", transaction_version_string); + + + return ret; +} + +/***********************************************************************/ + + +static gboolean +valid_transaction(const Transaction *com) +{ + return TRUE; +} + +static gboolean +gnc_transaction_end_handler(gpointer data_for_children, + GSList* data_from_children, GSList* sibling_data, + gpointer parent_data, gpointer global_data, + gpointer *result, const gchar *tag) +{ + Transaction *com; + xmlNodePtr achild; + xmlNodePtr tree = (xmlNodePtr)data_for_children; + + if(parent_data) + { + return TRUE; + } + + + if(!valid_transaction(com)) + { + return FALSE; + } + + return TRUE +} + + +sixtp* +gnc_transaction_sixtp_parser_create(void) +{ + return sixtp_dom_parser_new(gnc_transaction_end_handler); +} diff --git a/src/engine/gnc-xml.h b/src/engine/gnc-xml.h new file mode 100644 index 0000000000..03372b1b6c --- /dev/null +++ b/src/engine/gnc-xml.h @@ -0,0 +1,25 @@ + +#ifndef __GNC_XML_H__ +#define __GNC_XML_H__ + +#include "config.h" + +#include "gnc-xml-helper.h" + +#include "Account.h" +#include "gnc-commodity.h" + +#include "sixtp.h" + + +xmlNodePtr gnc_account_dom_tree_create(Account *act); +sixtp* gnc_account_sixtp_parser_create(void); + +xmlNodePtr gnc_commodity_dom_tree_create(const gnc_commodity *act); +sixtp* gnc_commodity_sixtp_parser_create(void); + +xmlNodePtr gnc_transaction_dom_tree_create(const Transaction *com); +sixtp* gnc_transaction_sixtp_parser_create(void); + + +#endif /* __GNC_XML_H__ */ diff --git a/src/engine/kvp_frame.c b/src/engine/kvp_frame.c index 3556991530..07d451a23b 100644 --- a/src/engine/kvp_frame.c +++ b/src/engine/kvp_frame.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "gnc-engine.h" #include "gnc-numeric.h" @@ -94,7 +95,7 @@ kvp_frame_new(void) { static void kvp_frame_delete_worker(gpointer key, gpointer value, gpointer user_data) { - g_cache_remove(gnc_string_cache, key); + g_cache_remove(gnc_engine_get_string_cache(), key); kvp_value_delete((kvp_value *)value); } @@ -120,7 +121,7 @@ kvp_frame_copy_worker(gpointer key, gpointer value, gpointer user_data) { kvp_frame * dest = (kvp_frame *)user_data; g_hash_table_freeze(dest->hash); g_hash_table_insert(dest->hash, - (gpointer)g_cache_insert(gnc_string_cache, key), + (gpointer)g_cache_insert(gnc_engine_get_string_cache(), key), (gpointer)kvp_value_copy(value)); g_hash_table_thaw(dest->hash); } @@ -159,13 +160,14 @@ kvp_frame_set_slot_destructively(kvp_frame * frame, const char * slot, & orig_key, & orig_value); if(key_exists) { g_hash_table_remove(frame->hash, slot); - g_cache_remove(gnc_string_cache, orig_key); + g_cache_remove(gnc_engine_get_string_cache(), orig_key); kvp_value_delete(orig_value); } if(new_value) { g_hash_table_insert(frame->hash, - g_cache_insert(gnc_string_cache, (gpointer) slot), + g_cache_insert(gnc_engine_get_string_cache(), + (gpointer) slot), new_value); } @@ -331,34 +333,45 @@ kvp_frame_get_frame_gslist (kvp_frame *frame, GSList *key_path) } } +static GSList* +charstar_va_list_to_gslist(va_list lst) +{ + const char *val; + GSList *ret = NULL; + + while(TRUE) + { + val = va_arg(lst, const char*); + + if(!val) + { + break; + } + + ret = g_slist_append(ret, (gpointer)val); + } + + return ret; +} + kvp_frame * -kvp_frame_get_frame (kvp_frame *frame, const char *first_key, ...) +kvp_frame_get_frame (kvp_frame *frame, ...) { va_list ap; - const char *key; GSList *lst; kvp_frame *ret; - if (!frame || !first_key) - return frame; + if (!frame) + return NULL; - va_start (ap, first_key); + va_start (ap, frame); - key = first_key; + lst = charstar_va_list_to_gslist(ap); + + ret = kvp_frame_get_frame_gslist(frame, lst); - lst = NULL; - - while (TRUE) { - lst = g_slist_append(lst, (gpointer) key); - - key = va_arg (ap, const char *); - if (!key) { - break; /* the normal exit to this routine. */ - } - } va_end (ap); - ret = kvp_frame_get_frame_gslist(frame, lst); g_slist_free(lst); return ret; @@ -548,7 +561,7 @@ kvp_glist_compare(const GList * list1, const GList * list2) { lp2 = lp2->next; } if(!lp1 && lp2) return -1; - if(!lp2) return 1; + if(!lp2 && lp1) return 1; return 0; } @@ -759,25 +772,6 @@ kvp_value_get_frame(const kvp_value * value) { /* manipulators */ -#if 0 -/* untested - didn't end up needing it... */ - -gboolean -kvp_value_binary_append(kvp_value *kv, void *data, guint64 size) { - void *new_data; - guint64 new_size; - - if(kv->type != KVP_TYPE_BINARY) return(FALSE); - new_size = kv->value.binary.datasize + size; - new_data = g_realloc(kv->value.binary.data, new_size); - if(!new_data) return(FALSE); - memcpy(kv->value.binary.data + kv->value.binary.datasize, data, size); - kv->value.binary.datasize = new_size; - return(TRUE); -} -#endif - - kvp_value * kvp_value_copy(const kvp_value * value) { @@ -827,7 +821,18 @@ kvp_frame_for_each_slot(kvp_frame *f, g_hash_table_foreach(f->hash, (GHFunc) proc, data); } -gboolean +gint +double_compare(double d1, double d2) +{ + if(isnan(d1) && isnan(d2)) return 0; + if((isinf(d1) == 1) && (isinf(d2) == 1)) return 0; + if((isinf(d1) == -1) && (isinf(d2) == -1)) return 0; + if(d1 < d2) return -1; + if(d1 > d2) return 1; + return 0; +} + +gint kvp_value_compare(const kvp_value * kva, const kvp_value * kvb) { if(kva == kvb) return 0; /* nothing is always less than something */ @@ -839,11 +844,13 @@ kvp_value_compare(const kvp_value * kva, const kvp_value * kvb) { switch(kva->type) { case KVP_TYPE_GINT64: - case KVP_TYPE_DOUBLE: if(kva->value.int64 < kvb->value.int64) return -1; if(kva->value.int64 > kvb->value.int64) return 1; return 0; break; + case KVP_TYPE_DOUBLE: + return double_compare(kva->value.dbl, kvb->value.dbl); + break; case KVP_TYPE_NUMERIC: return gnc_numeric_compare (kva->value.numeric, kvb->value.numeric); break; @@ -854,8 +861,10 @@ kvp_value_compare(const kvp_value * kva, const kvp_value * kvb) { return guid_compare(kva->value.guid, kvb->value.guid); break; case KVP_TYPE_BINARY: + /* I don't know that this is a good compare. Ab is bigger than Acef. + But I'm not sure that actually matters here. */ if(kva->value.binary.datasize < kvb->value.binary.datasize) return -1; - if(kva->value.binary.datasize < kvb->value.binary.datasize) return 1; + if(kva->value.binary.datasize > kvb->value.binary.datasize) return 1; return memcmp(kva->value.binary.data, kvb->value.binary.data, kva->value.binary.datasize); @@ -911,3 +920,155 @@ kvp_frame_compare(const kvp_frame *fa, const kvp_frame *fb) { return(status.compare); } + +gchar* +binary_to_string(const void *data, guint32 size) +{ + GString *output; + guint32 i; + guchar *data_str = (guchar*)data; + + output = g_string_sized_new(size * sizeof(char)); + + for(i = 0; i < size; i++) + { + g_string_sprintfa(output, "%02x", (unsigned int) (data_str[i])); + } + + return output->str; +} + +gchar* +kvp_value_glist_to_string(const GList *list) +{ + gchar *tmp1; + gchar *tmp2; + const GList *cursor; + + tmp1 = g_strdup_printf("[ "); + + for(cursor = list; cursor; cursor = cursor->next) + { + gchar *tmp3; + + tmp3 = kvp_value_to_string((kvp_value*)cursor->data); + tmp2 = g_strdup_printf("%s %s,", tmp1, tmp3); + g_free(tmp1); + g_free(tmp3); + tmp1 = tmp2; + } + + tmp2 = g_strdup_printf("%s ]", tmp1); + g_free(tmp1); + + return tmp2; +} + +gchar* +kvp_value_to_string(const kvp_value *val) +{ + gchar *tmp1; + gchar *tmp2; + + g_return_val_if_fail(val, NULL); + + switch(kvp_value_get_type(val)) + { + case KVP_TYPE_GINT64: + return g_strdup_printf("KVP_VALUE_GINT64(%lld)", + kvp_value_get_gint64(val)); + break; + + case KVP_TYPE_DOUBLE: + return g_strdup_printf("KVP_VALUE_DOUBLE(%g)", + kvp_value_get_double(val)); + break; + + case KVP_TYPE_NUMERIC: + tmp1 = gnc_numeric_to_string(kvp_value_get_numeric(val)); + tmp2 = g_strdup_printf("KVP_VALUE_NUMERIC(%s)", tmp1); + g_free(tmp1); + return tmp2; + break; + + case KVP_TYPE_STRING: + return g_strdup_printf("KVP_VALUE_STRING(%s)", + kvp_value_get_string(val)); + break; + + case KVP_TYPE_GUID: + tmp1 = guid_to_string(kvp_value_get_guid(val)); + tmp2 = g_strdup_printf("KVP_VALUE_GUID(%s)", tmp1); + g_free(tmp1); + return tmp2; + break; + + case KVP_TYPE_BINARY: + { + guint64 len; + void *data; + data = kvp_value_get_binary(val, &len); + tmp1 = binary_to_string(data, len); + return g_strdup_printf("KVP_VALUE_BINARY(%s)", tmp1); + } + break; + + case KVP_TYPE_GLIST: + tmp1 = kvp_value_glist_to_string(kvp_value_get_glist(val)); + tmp2 = g_strdup_printf("KVP_VALUE_GLIST(%s)", tmp1); + g_free(tmp1); + return tmp2; + break; + + case KVP_TYPE_FRAME: + tmp1 = kvp_frame_to_string(kvp_value_get_frame(val)); + tmp2 = g_strdup_printf("KVP_VALUE_FRAME(%s)", tmp1); + g_free(tmp1); + return tmp2; + break; + + default: + return g_strdup_printf(" "); + break; + } +} + +static void +kvp_frame_to_string_helper(gpointer key, gpointer value, gpointer data) +{ + gchar *tmp_val; + gchar **str = (gchar**)data; + gchar *old_data = *str; + + tmp_val = kvp_value_to_string((kvp_value*)value); + + *str = g_strdup_printf("%s %s => %s,\n", *str, (gchar*)key, tmp_val); + + g_free(old_data); + g_free(tmp_val); +} + +gchar* +kvp_frame_to_string(const kvp_frame *frame) +{ + gchar *tmp1; + + tmp1 = g_strdup_printf("{\n"); + + g_hash_table_foreach(frame->hash, kvp_frame_to_string_helper, &tmp1); + + { + gchar *tmp2; + tmp2 = g_strdup_printf("%s}\n", tmp1); + g_free(tmp1); + tmp1 = tmp2; + } + + return tmp1; +} + +GHashTable* +kvp_frame_get_hash(const kvp_frame *frame) +{ + return frame->hash; +} diff --git a/src/engine/kvp_frame.h b/src/engine/kvp_frame.h index 62314a98d6..88550a4871 100644 --- a/src/engine/kvp_frame.h +++ b/src/engine/kvp_frame.h @@ -62,11 +62,20 @@ kvp_frame * kvp_frame_new(void); void kvp_frame_delete(kvp_frame * frame); kvp_frame * kvp_frame_copy(const kvp_frame * frame); +gchar* kvp_frame_to_string(const kvp_frame *frame); +gchar* binary_to_string(const void *data, guint32 size); +gchar* kvp_value_glist_to_string(const GList *list); + +GHashTable* kvp_frame_get_hash(const kvp_frame *frame); + /* The kvp_frame_set_slot() routine copies the value into the frame, * associating it with 'key'. * The kvp_frame_set_slot_nc() routine puts the value (without copying * it) into the frame, associating it with 'key'. This routine is * handy for avoiding excess memory allocations & frees. + * Pointers passed as arguments into set_slot and get_slot are the + * responsibility of the caller. Pointers returned by get_slot are + * owned by the kvp_frame. Make copies as needed. */ void kvp_frame_set_slot(kvp_frame * frame, const char * key, const kvp_value * value); @@ -99,8 +108,7 @@ void kvp_frame_set_slot_path_gslist (kvp_frame *frame, * * */ -kvp_frame * kvp_frame_get_frame (kvp_frame *frame, - const char *first_key, ...); +kvp_frame * kvp_frame_get_frame (kvp_frame *frame, ...); kvp_frame * kvp_frame_get_frame_gslist (kvp_frame *frame, GSList *key_path); @@ -118,6 +126,7 @@ kvp_value * kvp_frame_get_slot_path_gslist (kvp_frame *frame, GSList *key_path); gint kvp_frame_compare(const kvp_frame *fa, const kvp_frame *fb); +gint double_compare(double v1, double v2); void kvp_value_delete(kvp_value * value); kvp_value * kvp_value_copy(const kvp_value * value); @@ -161,6 +170,8 @@ void * kvp_value_get_binary(const kvp_value * value, GList * kvp_value_get_glist(const kvp_value * value); kvp_frame * kvp_value_get_frame(const kvp_value * value); +gchar* kvp_value_to_string(const kvp_value *val); + /* manipulators */ gboolean kvp_value_binary_append(kvp_value *v, void *data, guint64 size); @@ -178,4 +189,5 @@ void kvp_frame_for_each_slot(kvp_frame *f, gpointer data), gpointer data); + #endif diff --git a/src/engine/sixtp-dom-generators.c b/src/engine/sixtp-dom-generators.c index 762d290704..5007e0fa2d 100644 --- a/src/engine/sixtp-dom-generators.c +++ b/src/engine/sixtp-dom-generators.c @@ -11,7 +11,7 @@ #include "kvp_frame.h" xmlNodePtr -guid_to_dom_tree(const char *tag, GUID* gid) +guid_to_dom_tree(const char *tag, const GUID* gid) { char *guid_str; xmlNodePtr ret; @@ -43,6 +43,11 @@ commodity_ref_to_dom_tree(const char *tag, const gnc_commodity *c) ret = xmlNewNode(NULL, tag); + if(!gnc_commodity_get_namespace(c) || !gnc_commodity_get_mnemonic(c)) + { + return NULL; + } + xmlNewTextChild(ret, NULL, "cmdty:space", gnc_commodity_get_namespace(c)); xmlNewTextChild(ret, NULL, "cmdty:id", gnc_commodity_get_mnemonic(c)); @@ -144,7 +149,135 @@ gnc_numeric_to_dom_tree(const char *tag, const gnc_numeric *num) return ret; } +gchar* +double_to_string(double value) +{ + gchar *numstr; +#ifdef USE_GUILE_FOR_DOUBLE_CONVERSION + numstr = gh_scm2newstr(gh_call1(gh_eval_str("number->string"), + gh_double2scm(value)), + NULL); + +#else /* don't USE_GUILE_FOR_DOUBLE_CONVERSION */ + /* + * we're just going to use plain-old libc for the double conversion. + * There was some question as to whether libc is accurate enough + * in its printf function for doubles, but I don't understand + * how it couldn't be ... + */ + numstr = g_strdup_printf ("%24.18g", value); + +#endif /* USE_GUILE_FOR_DOUBLE_CONVERSION */ + if(!numstr) + { + return NULL; + + } + else + { + return g_strstrip(numstr); + } +} + +static void +add_text_to_node(xmlNodePtr node, gchar *type, gchar *val) +{ + xmlSetProp(node, "type", type); + xmlNodeSetContent(node, val); + g_free(val); +} + + + +static void +add_kvp_slot(gpointer key, gpointer value, gpointer data); + +static void +add_kvp_value_node(xmlNodePtr node, gchar *tag, kvp_value* val) +{ + xmlNodePtr val_node; + gchar *tmp_str1; + + val_node = xmlNewChild(node, NULL, tag, NULL); + + switch(kvp_value_get_type(val)) + { + case KVP_TYPE_GINT64: + add_text_to_node(val_node, "integer", + g_strdup_printf("%lld", kvp_value_get_gint64(val))); + break; + case KVP_TYPE_DOUBLE: + add_text_to_node(val_node,"double", + double_to_string(kvp_value_get_double(val))); + break; + case KVP_TYPE_NUMERIC: + add_text_to_node(val_node,"numeric", + gnc_numeric_to_string(kvp_value_get_numeric(val))); + break; + case KVP_TYPE_STRING: + xmlSetProp(val_node, "type", "string"); + xmlNodeSetContent(val_node, kvp_value_get_string(val)); + break; + case KVP_TYPE_GUID: + add_text_to_node(val_node,"guid", + guid_to_string(kvp_value_get_guid(val))); + break; + case KVP_TYPE_BINARY: + { + guint64 size; + void *binary_data = kvp_value_get_binary(val, &size); + xmlSetProp(val_node, "type", "binary"); + g_return_if_fail(binary_data); + tmp_str1 = binary_to_string(binary_data, size); + xmlNodeSetContent(val_node, tmp_str1); + g_free(tmp_str1); + } + break; + case KVP_TYPE_GLIST: + { + GList *cursor; + + xmlSetProp(val_node, "type", "list"); + for(cursor = kvp_value_get_glist(val); cursor; cursor = cursor->next) + { + kvp_value *val = (kvp_value*)cursor->data; + add_kvp_value_node(val_node, "slot:value", val); + } + } + + break; + case KVP_TYPE_FRAME: + xmlSetProp(val_node, "type", "frame"); + g_hash_table_foreach(kvp_frame_get_hash(kvp_value_get_frame(val)), + add_kvp_slot, val_node); + break; + default: + break; + } +} + +static void +add_kvp_slot(gpointer key, gpointer value, gpointer data) +{ + xmlNodePtr slot_node; + xmlNodePtr node = (xmlNodePtr)data; + + slot_node = xmlNewChild(node, NULL, "slot", NULL); + + xmlNewTextChild(slot_node, NULL, "slot:key", (gchar*)key); + + add_kvp_value_node(slot_node, "slot:value", (kvp_value*)value); +} + xmlNodePtr kvp_frame_to_dom_tree(const char *tag, const kvp_frame *frame) { + xmlNodePtr ret; + + ret = xmlNewNode(NULL, tag); + + g_hash_table_foreach(kvp_frame_get_hash(frame), add_kvp_slot, ret); + + return ret; } + diff --git a/src/engine/sixtp-dom-generators.h b/src/engine/sixtp-dom-generators.h index ce92cfa095..9bbab80e56 100644 --- a/src/engine/sixtp-dom-generators.h +++ b/src/engine/sixtp-dom-generators.h @@ -12,12 +12,16 @@ #include "gnc-commodity.h" #include "date.h" #include "gnc-numeric.h" +#include "kvp_frame.h" -xmlNodePtr guid_to_dom_tree(const char *tag, GUID* gid); +xmlNodePtr guid_to_dom_tree(const char *tag, const GUID* gid); xmlNodePtr commodity_ref_to_dom_tree(const char *tag, const gnc_commodity *c); xmlNodePtr timespec_to_dom_tree(const char *tag, const Timespec *spec); gchar * timespec_nsec_to_string(const Timespec *ts); gchar * timespec_sec_to_string(const Timespec *ts); xmlNodePtr gnc_numeric_to_dom_tree(const char *tag, const gnc_numeric *num); +xmlNodePtr kvp_frame_to_dom_tree(const char *tag, const kvp_frame *frame); + +gchar* double_to_string(double value); #endif /* _SIXTP_DOM_GENERATORS_H_ */ diff --git a/src/engine/sixtp-dom-parsers.c b/src/engine/sixtp-dom-parsers.c index d95c5fa1e3..b6b4f7928b 100644 --- a/src/engine/sixtp-dom-parsers.c +++ b/src/engine/sixtp-dom-parsers.c @@ -51,11 +51,317 @@ dom_tree_to_guid(xmlNodePtr node) } } -kvp_frame* -dom_tree_handle_kvp(xmlNodePtr node) +kvp_value* +dom_tree_to_integer_kvp_value(xmlNodePtr node) { + gchar *text; + gint64 daint; + kvp_value* ret = NULL; + + text = dom_tree_to_text(node->xmlChildrenNode); - return FALSE; + if(string_to_gint64(text, &daint)) + { + ret = kvp_value_new_gint64(daint); + } + g_free(text); + + return ret; +} + +gboolean +dom_tree_to_integer(xmlNodePtr node, gint64 *daint) +{ + gchar *text; + + text = dom_tree_to_text(node->xmlChildrenNode); + + if(string_to_gint64(text, daint)) + { + return TRUE; + } + else + { + return FALSE; + } +} + +kvp_value* +dom_tree_to_double_kvp_value(xmlNodePtr node) +{ + gchar *text; + double dadoub; + kvp_value *ret = NULL; + + text = dom_tree_to_text(node->xmlChildrenNode); + + if(string_to_double(text, &dadoub)) + { + ret = kvp_value_new_double(dadoub); + } + + g_free(text); + + return ret; +} + +kvp_value* +dom_tree_to_numeric_kvp_value(xmlNodePtr node) +{ + gnc_numeric *danum; + kvp_value *ret = NULL; + + danum = dom_tree_to_gnc_numeric(node); + + if(danum) + { + ret = kvp_value_new_gnc_numeric(*danum); + } + + g_free(danum); + + return ret; +} + +kvp_value* +dom_tree_to_string_kvp_value(xmlNodePtr node) +{ + gchar *datext; + kvp_value *ret = NULL; + + datext = dom_tree_to_text(node->xmlChildrenNode); + if(datext) + { + ret = kvp_value_new_string(datext); + } + + g_free(datext); + + return ret; +} + +kvp_value* +dom_tree_to_guid_kvp_value(xmlNodePtr node) +{ + GUID *daguid; + kvp_value *ret = NULL; + + daguid = dom_tree_to_guid(node); + if(daguid) + { + ret = kvp_value_new_guid(daguid); + } + + g_free(daguid); + + return ret; +} + +gboolean +string_to_binary(const gchar *str, void **v, guint64 *data_len) +{ + guint64 str_len; + guchar *data; + int i, j; + + str_len = strlen(str); + + /* Since no whitespace is allowed and hex encoding is 2 text chars + per binary char, the result must be half the input size and the + input size must be even. */ + if((str_len % 2) != 0) + return(FALSE); + *data_len = str_len / 2; + data = g_new0(guchar, *data_len); + + g_return_val_if_fail(*v, FALSE); + + for(j = 0, i = 0; i < str_len; i += 2, j++) + { + gchar tmpstr[3]; + long int converted; + + tmpstr[0] = str[i]; + tmpstr[1] = str[i + 1]; + tmpstr[2] = '\0'; + + converted = strtol(tmpstr, NULL, 16); + + data[j] = (unsigned char)converted; + } + + *v = data; + + return(TRUE); +} + +kvp_value* +dom_tree_to_binary_kvp_value(xmlNodePtr node) +{ + gchar *text; + void *val; + guint64 len; + kvp_value *ret = NULL; + + text = dom_tree_to_text(node->xmlChildrenNode); + + if(string_to_binary(text, &val, &len)) + { + ret = kvp_value_new_binary_nc(val, len); + } + else + { + g_warning("string_to_binary returned false"); + } + + g_free(text); + + return ret; +} + +kvp_value* +dom_tree_to_list_kvp_value(xmlNodePtr node) +{ + GList *list = NULL; + xmlNodePtr mark; + kvp_value *ret = NULL; + + for(mark = node->xmlChildrenNode; mark; mark = mark->next) + { + kvp_value *new_val; + new_val = dom_tree_to_kvp_value(mark); + if(new_val) + { + list = g_list_append(list, (gpointer)new_val); + } + } + + if(list) + { + ret = kvp_value_new_glist_nc(list); + } + + return ret; +} + +kvp_value* +dom_tree_to_frame_kvp_value(xmlNodePtr node) +{ + kvp_frame *frame; + kvp_value *ret = NULL; + + frame = dom_tree_to_kvp_frame(node); + + if(frame) + { + ret = kvp_value_new_frame(frame); + } + + kvp_frame_delete(frame); + + return ret; +} + + +struct kvp_val_converter +{ + gchar *tag; + kvp_value* (*converter)(xmlNodePtr node); +}; + +struct kvp_val_converter val_converters[] = { + { "integer", dom_tree_to_integer_kvp_value }, + { "double", dom_tree_to_double_kvp_value }, + { "numeric", dom_tree_to_numeric_kvp_value }, + { "string", dom_tree_to_string_kvp_value }, + { "guid", dom_tree_to_guid_kvp_value }, + { "binary", dom_tree_to_binary_kvp_value }, + { "list", dom_tree_to_list_kvp_value }, + { "frame", dom_tree_to_frame_kvp_value }, + { 0, 0 }, +}; + +kvp_value* +dom_tree_to_kvp_value(xmlNodePtr node) +{ + gchar *type; + struct kvp_val_converter *mark; + kvp_value *ret = NULL; + + type = xmlGetProp(node, "type"); + if(!type) + { + type = g_strdup_printf("string"); + } + + for(mark = val_converters; mark->tag; mark++) + { + if(safe_strcmp(type, mark->tag) == 0) + { + ret = (mark->converter)(node); + } + } + + if(!mark->tag) + { + /* FIXME: deal with unknown type tag here */ + } + + g_free(type); + + return ret; +} + +kvp_frame* +dom_tree_to_kvp_frame(xmlNodePtr node) +{ + kvp_frame *ret; + xmlNodePtr mark; + + g_return_val_if_fail(node, NULL); + + ret = kvp_frame_new(); + + for(mark = node->xmlChildrenNode; mark; mark = mark->next) + { + if(safe_strcmp(mark->name, "slot") == 0) + { + xmlNodePtr mark2; + gchar *key = NULL; + kvp_value *val = NULL; + + for(mark2 = mark->xmlChildrenNode; mark2; mark2 = mark2->next) + { + if(safe_strcmp(mark2->name, "slot:key") == 0) + { + key = dom_tree_to_text(mark2->xmlChildrenNode); + } + else if(safe_strcmp(mark2->name, "slot:value") == 0) + { + val = dom_tree_to_kvp_value(mark2); + } + else + { + /* FIXME: should put some error here */ + } + } + + if(key) + { + if(val) + { + kvp_frame_set_slot_nc(ret, key, val); + } + else + { + /* FIXME: should put some error here */ + } + g_free(key); + } + } + } + + return ret; } @@ -302,5 +608,5 @@ associate_commodity_ref_with_engine_commodity(gnc_commodity *com) { return gnc_commodity_table_lookup(gnc_engine_commodities(), gnc_commodity_get_namespace(com), - gnc_commodity_get_exchange_code(com)); + gnc_commodity_get_mnemonic(com)); } diff --git a/src/engine/sixtp-dom-parsers.h b/src/engine/sixtp-dom-parsers.h index 5c60b85b13..b4c96968e7 100644 --- a/src/engine/sixtp-dom-parsers.h +++ b/src/engine/sixtp-dom-parsers.h @@ -24,7 +24,20 @@ gnc_commodity *dom_tree_to_commodity_ref_no_engine(xmlNodePtr node); Timespec* dom_tree_to_timespec(xmlNodePtr node); gnc_numeric* dom_tree_to_gnc_numeric(xmlNodePtr node); gchar * dom_tree_to_text(xmlNodePtr tree); +gboolean string_to_binary(const gchar *str, void **v, guint64 *data_len); + +kvp_frame* dom_tree_to_kvp_frame(xmlNodePtr node); +kvp_value* dom_tree_to_kvp_value(xmlNodePtr node); +kvp_value* dom_tree_to_integer_kvp_value(xmlNodePtr node); +kvp_value* dom_tree_to_double_kvp_value(xmlNodePtr node); +kvp_value* dom_tree_to_numeric_kvp_value(xmlNodePtr node); +kvp_value* dom_tree_to_string_kvp_value(xmlNodePtr node); +kvp_value* dom_tree_to_guid_kvp_value(xmlNodePtr node); +kvp_value* dom_tree_to_binary_kvp_value(xmlNodePtr node); +kvp_value* dom_tree_to_list_kvp_value(xmlNodePtr node); +kvp_value* dom_tree_to_frame_kvp_value(xmlNodePtr node); + +gboolean dom_tree_to_integer(xmlNodePtr node, gint64 *daint); -kvp_frame* dom_tree_handle_kvp(xmlNodePtr node); #endif /* _SIXTP_DOM_PARSERS_H_ */ diff --git a/src/engine/sixtp-to-dom-parser.c b/src/engine/sixtp-to-dom-parser.c index e64d725af2..ef39be7f70 100644 --- a/src/engine/sixtp-to-dom-parser.c +++ b/src/engine/sixtp-to-dom-parser.c @@ -6,8 +6,10 @@ #include "sixtp-utils.h" #include "sixtp.h" -static xmlNsPtr global_namespace; +static xmlNsPtr global_namespace = NULL; +/* Don't pass anything in the data_for_children value to this + function. It'll cause a segfault */ static gboolean dom_start_handler( GSList* sibling_data, gpointer parent_data, gpointer global_data, gpointer *data_for_children, gpointer *result, const gchar *tag, @@ -22,7 +24,8 @@ static gboolean dom_start_handler( } else { - thing = xmlNewChild(parent_data, global_namespace, tag, NULL); + thing = xmlNewChild((xmlNodePtr)parent_data, global_namespace, + tag, NULL); } if(attrs != NULL) @@ -40,26 +43,12 @@ static gboolean dom_start_handler( return TRUE; } -static gboolean is_whitespace(const char *text, int len) -{ - int i; - for(i = 0; i < len; i++) - { - if(!isspace(text[i])) - { - return FALSE; - } - } - return TRUE; -} - static gboolean dom_chars_handler( GSList *sibling_data, gpointer parent_data, gpointer global_data, gpointer *result, const char *text, int length) { - if(length > 0 && !is_whitespace(text, length)) + if(length > 0 && !isspace_str(text, length)) { - /* gchar *stuff = g_strndup(text, length); */ xmlNodeSetContentLen((xmlNodePtr)parent_data, text, length); } return TRUE; diff --git a/src/register/QuickFill.c b/src/register/QuickFill.c index c2db6470b4..76243a07cc 100644 --- a/src/register/QuickFill.c +++ b/src/register/QuickFill.c @@ -86,7 +86,7 @@ gnc_quickfill_new (void) /* For now, use the engine cache. */ if (qf_string_cache == NULL) - qf_string_cache = gnc_string_cache; + qf_string_cache = gnc_engine_get_string_cache (); qf = g_new (QuickFill, 1);