From f335a5b7222df36ab2bf7082e55df5213c18aa03 Mon Sep 17 00:00:00 2001 From: Dave Peticolas Date: Thu, 15 Feb 2001 00:17:57 +0000 Subject: [PATCH] James LewisMoss's patch. * src/test/test-date-converting.c (Repository): Tests to make sure date <-> string converting strings work. * src/test/test-dom-converters1.c (Repository): Add tests for rest of converters. * src/test/Makefile.am (Repository): add new test. Make "make check" work here. * src/engine/sixtp-xml-write-utils.c (Repository): use date format strings from sixtp-utils.h * src/engine/sixtp-utils.h (Repository): add date format strings. #include sixtp.h * src/engine/sixtp-utils.c (Repository): Use define as timespec date format string. * src/engine/sixtp-dom-parsers.c (Repository): Add funcs from Rob. make consistent. Fix a few bugs. Make dom_tree_to_commodity_ref testable by adding new func "associate_commodity_ref_with_engine_commodity" to do final association with engine commodity table. * src/engine/sixtp-dom-generators.c (Repository): Fix to_guid to be generic. Oops. Add rest of funcs to to foo_to_dom_tree to match funcs in sixtp_dom_parsers. * src/engine/gnc-numeric.c (Repository): Comment out unused var. * src/engine/gnc-account-xml-v2.c (Repository): change to use dom_tree_to_commodity_ref. * src/doc/xml/types.dtd: Change cmd: to cmdty: and add ts: to the timespec tags. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@3659 57a11ea4-9604-0410-9ed3-97b8803252fd --- ChangeLog | 38 +++++ debian/changelog | 2 +- debian/control | 1 + src/doc/xml/types.dtd | 12 +- src/engine/gnc-account-xml-v2.c | 14 +- src/engine/gnc-numeric.c | 2 +- src/engine/sixtp-dom-generators.c | 116 +++++++++++++- src/engine/sixtp-dom-generators.h | 11 +- src/engine/sixtp-dom-parsers.c | 242 ++++++++++++++++++++++++++++- src/engine/sixtp-dom-parsers.h | 10 +- src/engine/sixtp-utils.c | 2 +- src/engine/sixtp-utils.h | 4 + src/engine/sixtp-xml-write-utils.c | 3 +- 13 files changed, 433 insertions(+), 24 deletions(-) diff --git a/ChangeLog b/ChangeLog index 71aec88018..ffa92ac517 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,41 @@ +2001-02-14 James LewisMoss + + * src/test/test-date-converting.c (Repository): Tests to make sure + date <-> string converting strings work. + + * src/test/test-dom-converters1.c (Repository): Add tests for rest + of converters. + + * src/test/Makefile.am (Repository): add new test. Make "make + check" work here. + + * src/engine/sixtp-xml-write-utils.c (Repository): use date format + strings from sixtp-utils.h + + * src/engine/sixtp-utils.h (Repository): add date format strings. + #include sixtp.h + + * src/engine/sixtp-utils.c (Repository): Use define as timespec + date format string. + + * src/engine/sixtp-dom-parsers.c (Repository): Add funcs from + Rob. make consistent. Fix a few bugs. Make + dom_tree_to_commodity_ref testable by adding new func + "associate_commodity_ref_with_engine_commodity" to do final + association with engine commodity table. + + * src/engine/sixtp-dom-generators.c (Repository): Fix to_guid to + be generic. Oops. Add rest of funcs to to foo_to_dom_tree to + match funcs in sixtp_dom_parsers. + + * src/engine/gnc-numeric.c (Repository): Comment out unused var. + + * src/engine/gnc-account-xml-v2.c (Repository): change to use + dom_tree_to_commodity_ref. + + * src/doc/xml/types.dtd: Change cmd: to cmdty: and add ts: to the + timespec tags. + 2001-02-14 Dave Peticolas * src/engine/date.c: use nl_langinfo (D_FMT) instead of %x for diff --git a/debian/changelog b/debian/changelog index ce7ced944f..12bcc3c9c0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -gnucash (1.5.2.cvs20010124-test1-0.1) unstable; urgency=low +gnucash (1.5.2.cvs20010212-0.1) unstable; urgency=low * local cvs compile diff --git a/debian/control b/debian/control index 42c4066793..c678c553d4 100644 --- a/debian/control +++ b/debian/control @@ -3,6 +3,7 @@ Section: utils Priority: extra Maintainer: John Goerzen Standards-Version: 3.1.0.0 +Build-Depends: libguppi-dev, libguile-dev, libgtkhtml-dev, libxml-dev, libart-dev, libgnome-dev, libgwrapguile-dev, libglib1.2-dev Package: gnucash Architecture: any diff --git a/src/doc/xml/types.dtd b/src/doc/xml/types.dtd index 75bfe1fd6b..1d04229905 100644 --- a/src/doc/xml/types.dtd +++ b/src/doc/xml/types.dtd @@ -2,10 +2,10 @@ - - + + - + @@ -20,7 +20,7 @@ - - + + - + diff --git a/src/engine/gnc-account-xml-v2.c b/src/engine/gnc-account-xml-v2.c index 375256e189..2170094fa5 100644 --- a/src/engine/gnc-account-xml-v2.c +++ b/src/engine/gnc-account-xml-v2.c @@ -8,6 +8,7 @@ #include "sixtp.h" #include "sixtp-utils.h" #include "sixtp-parsers.h" +#include "sixtp-utils.h" #include "sixtp-dom-parsers.h" #include "AccountP.h" @@ -55,14 +56,23 @@ account_type_handler (xmlNodePtr node, Account* act) static gboolean account_currency_handler (xmlNodePtr node, Account* act) { - xaccAccountSetCurrency(act, dom_tree_to_gnc_commodity(node)); + gnc_commodity *ref; + + ref = dom_tree_to_commodity_ref(node); + xaccAccountSetCurrency( + act, associate_commodity_ref_with_engine_commodity(ref)); + gnc_commodity_destroy(ref); return TRUE; } static gboolean account_security_handler (xmlNodePtr node, Account* act) { - xaccAccountSetCurrency(act, dom_tree_to_gnc_commodity(node)); + gnc_commodity *ref; + ref = dom_tree_to_commodity_ref(node); + xaccAccountSetSecurity( + act, associate_commodity_ref_with_engine_commodity(ref)); + gnc_commodity_destroy(ref); return TRUE; } diff --git a/src/engine/gnc-numeric.c b/src/engine/gnc-numeric.c index 5c6e2f734d..94cb3eb336 100644 --- a/src/engine/gnc-numeric.c +++ b/src/engine/gnc-numeric.c @@ -37,7 +37,7 @@ * 64-bit-overflow-proof */ -static short module = MOD_ENGINE; +/* static short module = MOD_ENGINE; */ static const char * _numeric_error_strings[] = { diff --git a/src/engine/sixtp-dom-generators.c b/src/engine/sixtp-dom-generators.c index 1e61da7a52..eaaef36416 100644 --- a/src/engine/sixtp-dom-generators.c +++ b/src/engine/sixtp-dom-generators.c @@ -5,16 +5,18 @@ #include "gnc-xml-helper.h" #include "sixtp-dom-generators.h" +#include "sixtp-utils.h" + #include "GNCId.h" xmlNodePtr -guid_to_dom_tree(GUID* gid) +guid_to_dom_tree(const char *tag, GUID* gid) { char *guid_str; xmlNodePtr ret; - ret = xmlNewNode(NULL, "test-guid"); + ret = xmlNewNode(NULL, tag); xmlSetProp(ret, "type", "guid"); @@ -29,3 +31,113 @@ guid_to_dom_tree(GUID* gid) return ret; } + +xmlNodePtr +commodity_ref_to_dom_tree(const char *tag, const gnc_commodity *c) +{ + xmlNodePtr ret; + + g_return_val_if_fail(c, NULL); + + ret = xmlNewNode(NULL, tag); + + xmlNewTextChild(ret, NULL, "cmdty:space", gnc_commodity_get_namespace(c)); + xmlNewTextChild(ret, NULL, "cmdty:id", gnc_commodity_get_mnemonic(c)); + + return ret; +} + +gchar * +timespec_sec_to_string(const Timespec *ts) +{ + gchar *ret; + struct tm parsed_time; + time_t tmp_time; + + ret = g_new(gchar, 512); + + tmp_time = ts->tv_sec; + + if(!localtime_r(&tmp_time, &parsed_time)) + { + g_free(ret); + return NULL; + } + + if(strftime(ret, 512, TIMESPEC_TIME_FORMAT, &parsed_time) == 0) + { + g_free(ret); + return NULL; + } + + return ret; +} + +gchar * +timespec_nsec_to_string(const Timespec *ts) +{ + gchar *ret; + + ret = g_new(gchar, 22); + + g_snprintf(ret, 22, "%ld", ts->tv_nsec); + + return ret; +} + +xmlNodePtr +timespec_to_dom_tree(const char *tag, const Timespec *spec) +{ + xmlNodePtr ret; + gchar *date_str; + gchar *ns_str; + + g_return_val_if_fail(spec, NULL); + + + date_str = timespec_sec_to_string(spec); + ns_str = timespec_nsec_to_string(spec); + + if((!date_str && !ns_str) || !date_str) + { + if(ns_str) + { + g_free(ns_str); + } + return NULL; + } + + ret = xmlNewNode(NULL, tag); + + xmlNewTextChild(ret, NULL, "ts:date", date_str); + + if(ns_str) + { + xmlNewTextChild(ret, NULL, "ts:ns", ns_str); + } + + g_free(date_str); + g_free(ns_str); + + return ret; +} + +xmlNodePtr +gnc_numeric_to_dom_tree(const char *tag, const gnc_numeric *num) +{ + xmlNodePtr ret; + gchar *numstr; + + g_return_val_if_fail(num, NULL); + + numstr = gnc_numeric_to_string(*num); + g_return_val_if_fail(numstr, NULL); + + ret = xmlNewNode(NULL, tag); + + xmlNodeAddContent(ret, numstr); + + g_free(numstr); + + return ret; +} diff --git a/src/engine/sixtp-dom-generators.h b/src/engine/sixtp-dom-generators.h index e5fea43d89..ce92cfa095 100644 --- a/src/engine/sixtp-dom-generators.h +++ b/src/engine/sixtp-dom-generators.h @@ -9,8 +9,15 @@ #include "sixtp-dom-generators.h" #include "GNCId.h" +#include "gnc-commodity.h" +#include "date.h" +#include "gnc-numeric.h" - -xmlNodePtr guid_to_dom_tree(GUID* gid); +xmlNodePtr guid_to_dom_tree(const char *tag, 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); #endif /* _SIXTP_DOM_GENERATORS_H_ */ diff --git a/src/engine/sixtp-dom-parsers.c b/src/engine/sixtp-dom-parsers.c index 47e0897f25..a0263b14c8 100644 --- a/src/engine/sixtp-dom-parsers.c +++ b/src/engine/sixtp-dom-parsers.c @@ -4,10 +4,16 @@ #include #include "gnc-xml-helper.h" +#include "gnc-engine-util.h" +#include "gnc-commodity.h" +#include "gnc-engine.h" +#include "sixtp-utils.h" #include "sixtp-dom-parsers.h" #include "GNCId.h" +static short module = MOD_IO; + GUID* dom_tree_to_guid(xmlNodePtr node) { @@ -45,13 +51,6 @@ dom_tree_to_guid(xmlNodePtr node) } } -gnc_commodity* -dom_tree_to_gnc_commodity(xmlNodePtr node) -{ - - return NULL; -} - gboolean dom_tree_handle_kvp(kvp_frame* frame, xmlNodePtr node) { @@ -59,3 +58,232 @@ dom_tree_handle_kvp(kvp_frame* frame, xmlNodePtr node) return FALSE; } + +gchar * +dom_tree_to_text(xmlNodePtr tree) +{ + /* Expect *only* text and comment sibling nodes. Ignore comment + nodes and collapse text nodes into one string. Return NULL if + expectations are unsatisfied. + + If there are a lot of text sub-nodes, this algorithm may be + inefficient because it'll reallocate a lot. + + */ + + gboolean ok = TRUE; + xmlNodePtr current; + gchar *result = g_strdup(""); + gchar *temp; + + for(current = tree; current; current = current->next) { + switch(current->type) { + case XML_TEXT_NODE: + temp = g_strconcat(result, (gchar *) current->content, NULL); + g_free(result); + result = temp; + break; + case XML_COMMENT_NODE: + break; + default: + PERR("dom_tree_to_text: hit illegal node type while extracting text."); + current = NULL; + ok = FALSE; + break; + }; + } + + if(!ok) { + if(result) g_free(result); + result = NULL; + } + return result; +} + +gnc_numeric* +dom_tree_to_gnc_numeric(xmlNodePtr node) +{ + gchar *content = dom_tree_to_text(node->xmlChildrenNode); + gnc_numeric *ret; + if(!content) + return NULL; + + ret = g_new(gnc_numeric, 1); + + if(string_to_gnc_numeric(content, ret) != NULL) + { + return ret; + } + else + { + g_free(ret); + return NULL; + } +} + +static Timespec* +timespec_failure(Timespec *would_have_been) +{ + if(would_have_been) + { + g_free(would_have_been); + } + return NULL; +} + + +Timespec* +dom_tree_to_timespec(xmlNodePtr node) +{ + /* Turn something like this + + + Mon, 05 Jun 2000 23:16:19 -0500 + 658864000 + + + into a Timespec. If this returns FALSE, the effects on *ts are + undefined. The XML is valid if it has at least one of or + and no more than one of each. Order is irrelevant. */ + + Timespec *ret; + gboolean seen_s = FALSE; + gboolean seen_ns = FALSE; + xmlNodePtr n; + + ret = g_new(Timespec, 1); + + ret->tv_sec = 0; + ret->tv_nsec = 0; + for(n = node->xmlChildrenNode; n; n = n->next) { + switch(n->type) { + case XML_COMMENT_NODE: + break; + case XML_ELEMENT_NODE: + if(safe_strcmp("ts:date", n->name) == 0) { + if(seen_s) + { + return timespec_failure(ret); + } + else + { + gchar *content = dom_tree_to_text(n->xmlChildrenNode); + if(!content) + { + return timespec_failure(ret); + } + + if(!string_to_timespec_secs(content, ret)) { + free(content); + return timespec_failure(ret); + } + seen_s = TRUE; + } + } + else if(safe_strcmp("ts:ns", n->name) == 0) { + if(seen_ns) + { + return timespec_failure(ret); + } + else + { + gchar *content = dom_tree_to_text(n->xmlChildrenNode); + if(!content) + { + return timespec_failure(ret); + } + + if(!string_to_timespec_nsecs(content, ret)) { + free(content); + return timespec_failure(ret); + } + seen_ns = TRUE; + } + } + break; + default: + PERR("dom_tree_to_timespec: unexpected sub-node."); + return timespec_failure(ret); + break; + } + } + + if(!seen_s) + { + g_warning("dom_tree_to_timespec: no ts:date node found."); + return timespec_failure(ret); + } + + return ret; +} + +gnc_commodity * +dom_tree_to_commodity_ref(xmlNodePtr node) +{ + /* Turn something like this + + + NASDAQ + LNUX + + + into a gnc_commodity*, returning NULL on failure. Both sub-nodes + are required, though for now, order is irrelevant. */ + + gnc_commodity *c = NULL; + gchar *space_str = NULL; + gchar *id_str = NULL; + xmlNodePtr n; + + if(!node) return NULL; + if(!node->xmlChildrenNode) return NULL; + + for(n = node->xmlChildrenNode; n; n = n->next) { + switch(n->type) { + case XML_COMMENT_NODE: + break; + case XML_ELEMENT_NODE: + if(safe_strcmp("cmdty:space", n->name) == 0) { + if(space_str) { + return NULL; + } else { + gchar *content = dom_tree_to_text(n->xmlChildrenNode); + if(!content) return NULL; + space_str = content; + } + } else if(safe_strcmp("cmdty:id", n->name) == 0) { + if(id_str) { + return NULL; + } else { + gchar *content = dom_tree_to_text(n->xmlChildrenNode); + if(!content) return NULL; + id_str = content; + } + } + break; + default: + PERR("dom_tree_to_timespec: unexpected sub-node."); + return NULL; + break; + } + } + if(!(space_str && id_str)) { + c = NULL; + } else { + g_strstrip(space_str); + g_strstrip(id_str); + c = gnc_commodity_new(NULL, space_str, id_str, NULL, 0); + } + + if(space_str) g_free(space_str); + if(id_str) g_free(id_str); + return c; +} + +gnc_commodity * +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)); +} diff --git a/src/engine/sixtp-dom-parsers.h b/src/engine/sixtp-dom-parsers.h index b1d6cf7224..5f6f6c007b 100644 --- a/src/engine/sixtp-dom-parsers.h +++ b/src/engine/sixtp-dom-parsers.h @@ -9,12 +9,20 @@ #include "gnc-commodity.h" #include "kvp_frame.h" +#include "date.h" +#include "gnc-numeric.h" #include "GNCId.h" GUID* dom_tree_to_guid(xmlNodePtr node); -gnc_commodity* dom_tree_to_gnc_commodity(xmlNodePtr node); +gnc_commodity* dom_tree_to_commodity_ref(xmlNodePtr node); +gnc_commodity* associate_commodity_ref_with_engine_commodity( + gnc_commodity *com); + +Timespec* dom_tree_to_timespec(xmlNodePtr node); +gnc_numeric* dom_tree_to_gnc_numeric(xmlNodePtr node); +gchar * dom_tree_to_text(xmlNodePtr tree); gboolean dom_tree_handle_kvp(kvp_frame* frame, xmlNodePtr node); diff --git a/src/engine/sixtp-utils.c b/src/engine/sixtp-utils.c index 19c555a59c..0dda32709b 100644 --- a/src/engine/sixtp-utils.c +++ b/src/engine/sixtp-utils.c @@ -343,7 +343,7 @@ string_to_timespec_secs(const gchar *str, Timespec *ts) { /* If you change this, make sure you also change the output code, if necessary. */ /*fprintf(stderr, "parsing (%s)\n", str);*/ - strpos = strptime(str, "%Y-%m-%d %H:%M:%S", &parsed_time); + strpos = strptime(str, TIMESPEC_PARSE_TIME_FORMAT, &parsed_time); g_return_val_if_fail(strpos, FALSE); diff --git a/src/engine/sixtp-utils.h b/src/engine/sixtp-utils.h index fcd909033b..3ff20d3cc9 100644 --- a/src/engine/sixtp-utils.h +++ b/src/engine/sixtp-utils.h @@ -4,12 +4,16 @@ #include "date.h" +#include "sixtp.h" + typedef struct { Timespec ts; guint s_block_count; guint ns_block_count; } TimespecParseInfo; +#define TIMESPEC_TIME_FORMAT "%Y-%m-%d %H:%M:%S %z" +#define TIMESPEC_PARSE_TIME_FORMAT "%Y-%m-%d %H:%M:%S" gboolean isspace_str(const gchar *str, int nomorethan); diff --git a/src/engine/sixtp-xml-write-utils.c b/src/engine/sixtp-xml-write-utils.c index e4d6f47c67..3b23327488 100644 --- a/src/engine/sixtp-xml-write-utils.c +++ b/src/engine/sixtp-xml-write-utils.c @@ -10,6 +10,7 @@ #include "gnc-xml-helper.h" #include "sixtp-xml-write-utils.h" +#include "sixtp-utils.h" #include "gnc-numeric.h" #include "gnc-engine-util.h" @@ -225,7 +226,7 @@ xml_add_editable_timespec(xmlNodePtr p, if(!localtime_r(&tmp_timet, &parsed_time)) return(FALSE); num_written = strftime(secs_str, sizeof(secs_str), - "%Y-%m-%d %H:%M:%S %z", + TIMESPEC_TIME_FORMAT, &parsed_time); if(num_written == 0) return(FALSE);