[Gnucash-changes] r11917 - gnucash/trunk - move QOF files to
lib/libqof/
Neil Williams
codehelp at cvs.gnucash.org
Sun Nov 13 08:22:40 EST 2005
Author: codehelp
Date: 2005-11-13 08:22:34 -0500 (Sun, 13 Nov 2005)
New Revision: 11917
Trac: http://svn.gnucash.org/trac/changeset/11917
Added:
gnucash/trunk/lib/libqof/
gnucash/trunk/lib/libqof/Makefile.am
gnucash/trunk/lib/libqof/backend/
gnucash/trunk/lib/libqof/backend/Makefile.am
gnucash/trunk/lib/libqof/backend/file/
gnucash/trunk/lib/libqof/backend/file/Makefile.am
gnucash/trunk/lib/libqof/backend/file/pilot-qsf-GnuCashInvoice.xml
gnucash/trunk/lib/libqof/backend/file/qof-backend-qsf.h
gnucash/trunk/lib/libqof/backend/file/qsf-backend.c
gnucash/trunk/lib/libqof/backend/file/qsf-dir.h.in
gnucash/trunk/lib/libqof/backend/file/qsf-map.xsd.xml
gnucash/trunk/lib/libqof/backend/file/qsf-object.xsd.xml
gnucash/trunk/lib/libqof/backend/file/qsf-xml-map.c
gnucash/trunk/lib/libqof/backend/file/qsf-xml.c
gnucash/trunk/lib/libqof/backend/file/qsf-xml.h
gnucash/trunk/lib/libqof/qof/
gnucash/trunk/lib/libqof/qof/Makefile.am
gnucash/trunk/lib/libqof/qof/gnc-date.c
gnucash/trunk/lib/libqof/qof/gnc-date.h
gnucash/trunk/lib/libqof/qof/gnc-engine-util.c
gnucash/trunk/lib/libqof/qof/gnc-engine-util.h
gnucash/trunk/lib/libqof/qof/gnc-event-p.h
gnucash/trunk/lib/libqof/qof/gnc-event.c
gnucash/trunk/lib/libqof/qof/gnc-event.h
gnucash/trunk/lib/libqof/qof/gnc-numeric.c
gnucash/trunk/lib/libqof/qof/gnc-numeric.h
gnucash/trunk/lib/libqof/qof/gnc-trace.c
gnucash/trunk/lib/libqof/qof/gnc-trace.h
gnucash/trunk/lib/libqof/qof/guid.c
gnucash/trunk/lib/libqof/qof/guid.h
gnucash/trunk/lib/libqof/qof/kvp-util-p.h
gnucash/trunk/lib/libqof/qof/kvp-util.c
gnucash/trunk/lib/libqof/qof/kvp-util.h
gnucash/trunk/lib/libqof/qof/kvp_frame.c
gnucash/trunk/lib/libqof/qof/kvp_frame.h
gnucash/trunk/lib/libqof/qof/md5.c
gnucash/trunk/lib/libqof/qof/md5.h
gnucash/trunk/lib/libqof/qof/qof-be-utils.h
gnucash/trunk/lib/libqof/qof/qof.h
gnucash/trunk/lib/libqof/qof/qof_book_merge.c
gnucash/trunk/lib/libqof/qof/qof_book_merge.h
gnucash/trunk/lib/libqof/qof/qofbackend-p.h
gnucash/trunk/lib/libqof/qof/qofbackend.c
gnucash/trunk/lib/libqof/qof/qofbackend.h
gnucash/trunk/lib/libqof/qof/qofbook-p.h
gnucash/trunk/lib/libqof/qof/qofbook.c
gnucash/trunk/lib/libqof/qof/qofbook.h
gnucash/trunk/lib/libqof/qof/qofchoice.c
gnucash/trunk/lib/libqof/qof/qofchoice.h
gnucash/trunk/lib/libqof/qof/qofclass-p.h
gnucash/trunk/lib/libqof/qof/qofclass.c
gnucash/trunk/lib/libqof/qof/qofclass.h
gnucash/trunk/lib/libqof/qof/qofgobj.c
gnucash/trunk/lib/libqof/qof/qofgobj.h
gnucash/trunk/lib/libqof/qof/qofid-p.h
gnucash/trunk/lib/libqof/qof/qofid.c
gnucash/trunk/lib/libqof/qof/qofid.h
gnucash/trunk/lib/libqof/qof/qofinstance-p.h
gnucash/trunk/lib/libqof/qof/qofinstance.c
gnucash/trunk/lib/libqof/qof/qofinstance.h
gnucash/trunk/lib/libqof/qof/qofla-dir.h.in
gnucash/trunk/lib/libqof/qof/qofmath128.c
gnucash/trunk/lib/libqof/qof/qofmath128.h
gnucash/trunk/lib/libqof/qof/qofobject-p.h
gnucash/trunk/lib/libqof/qof/qofobject.c
gnucash/trunk/lib/libqof/qof/qofobject.h
gnucash/trunk/lib/libqof/qof/qofquery-deserial.c
gnucash/trunk/lib/libqof/qof/qofquery-deserial.h
gnucash/trunk/lib/libqof/qof/qofquery-p.h
gnucash/trunk/lib/libqof/qof/qofquery-serialize.c
gnucash/trunk/lib/libqof/qof/qofquery-serialize.h
gnucash/trunk/lib/libqof/qof/qofquery.c
gnucash/trunk/lib/libqof/qof/qofquery.h
gnucash/trunk/lib/libqof/qof/qofquerycore-p.h
gnucash/trunk/lib/libqof/qof/qofquerycore.c
gnucash/trunk/lib/libqof/qof/qofquerycore.h
gnucash/trunk/lib/libqof/qof/qofsession-p.h
gnucash/trunk/lib/libqof/qof/qofsession.c
gnucash/trunk/lib/libqof/qof/qofsession.h
gnucash/trunk/lib/libqof/qof/qofsql.c
gnucash/trunk/lib/libqof/qof/qofsql.h
Removed:
gnucash/trunk/src/backend/qsf/Makefile.am
gnucash/trunk/src/backend/qsf/pilot-qsf-GnuCashInvoice.xml
gnucash/trunk/src/backend/qsf/qof-backend-qsf.h
gnucash/trunk/src/backend/qsf/qsf-backend.c
gnucash/trunk/src/backend/qsf/qsf-dir.h.in
gnucash/trunk/src/backend/qsf/qsf-map.xsd.xml
gnucash/trunk/src/backend/qsf/qsf-object.xsd.xml
gnucash/trunk/src/backend/qsf/qsf-xml-map.c
gnucash/trunk/src/backend/qsf/qsf-xml.c
gnucash/trunk/src/backend/qsf/qsf-xml.h
gnucash/trunk/src/engine/gnc-date.c
gnucash/trunk/src/engine/gnc-date.h
gnucash/trunk/src/engine/gnc-engine-util.c
gnucash/trunk/src/engine/gnc-engine-util.h
gnucash/trunk/src/engine/gnc-event-p.h
gnucash/trunk/src/engine/gnc-event.c
gnucash/trunk/src/engine/gnc-event.h
gnucash/trunk/src/engine/gnc-numeric.c
gnucash/trunk/src/engine/gnc-numeric.h
gnucash/trunk/src/engine/gnc-trace.c
gnucash/trunk/src/engine/gnc-trace.h
gnucash/trunk/src/engine/guid.c
gnucash/trunk/src/engine/guid.h
gnucash/trunk/src/engine/kvp-util-p.h
gnucash/trunk/src/engine/kvp-util.c
gnucash/trunk/src/engine/kvp-util.h
gnucash/trunk/src/engine/kvp_frame.c
gnucash/trunk/src/engine/kvp_frame.h
gnucash/trunk/src/engine/md5.c
gnucash/trunk/src/engine/md5.h
gnucash/trunk/src/engine/qof-be-utils.h
gnucash/trunk/src/engine/qof.h
gnucash/trunk/src/engine/qof_book_merge.c
gnucash/trunk/src/engine/qof_book_merge.h
gnucash/trunk/src/engine/qofbackend-p.h
gnucash/trunk/src/engine/qofbackend.c
gnucash/trunk/src/engine/qofbackend.h
gnucash/trunk/src/engine/qofbook-p.h
gnucash/trunk/src/engine/qofbook.c
gnucash/trunk/src/engine/qofbook.h
gnucash/trunk/src/engine/qofchoice.c
gnucash/trunk/src/engine/qofchoice.h
gnucash/trunk/src/engine/qofclass-p.h
gnucash/trunk/src/engine/qofclass.c
gnucash/trunk/src/engine/qofclass.h
gnucash/trunk/src/engine/qofgobj.c
gnucash/trunk/src/engine/qofgobj.h
gnucash/trunk/src/engine/qofid-p.h
gnucash/trunk/src/engine/qofid.c
gnucash/trunk/src/engine/qofid.h
gnucash/trunk/src/engine/qofinstance-p.h
gnucash/trunk/src/engine/qofinstance.c
gnucash/trunk/src/engine/qofinstance.h
gnucash/trunk/src/engine/qofla-dir.h.in
gnucash/trunk/src/engine/qofmath128.c
gnucash/trunk/src/engine/qofmath128.h
gnucash/trunk/src/engine/qofobject-p.h
gnucash/trunk/src/engine/qofobject.c
gnucash/trunk/src/engine/qofobject.h
gnucash/trunk/src/engine/qofquery-deserial.c
gnucash/trunk/src/engine/qofquery-deserial.h
gnucash/trunk/src/engine/qofquery-p.h
gnucash/trunk/src/engine/qofquery-serialize.c
gnucash/trunk/src/engine/qofquery-serialize.h
gnucash/trunk/src/engine/qofquery.c
gnucash/trunk/src/engine/qofquery.h
gnucash/trunk/src/engine/qofquerycore-p.h
gnucash/trunk/src/engine/qofquerycore.c
gnucash/trunk/src/engine/qofquerycore.h
gnucash/trunk/src/engine/qofsession-p.h
gnucash/trunk/src/engine/qofsession.c
gnucash/trunk/src/engine/qofsession.h
gnucash/trunk/src/engine/qofsql.c
gnucash/trunk/src/engine/qofsql.h
Modified:
gnucash/trunk/ChangeLog
gnucash/trunk/configure.in
gnucash/trunk/lib/Makefile.am
gnucash/trunk/src/backend/Makefile.am
gnucash/trunk/src/backend/postgres/test/Makefile.am
gnucash/trunk/src/backend/postgres/test/test-load-backend.c
gnucash/trunk/src/engine/Makefile.am
gnucash/trunk/src/gnome-utils/test/Makefile.am
gnucash/trunk/src/import-export/qif-import/test/Makefile.am
Log:
move QOF files to lib/libqof/
Modified: gnucash/trunk/ChangeLog
===================================================================
--- gnucash/trunk/ChangeLog 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/ChangeLog 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,3 +1,96 @@
+2005-11-13 Neil Williams <linux at codehelp.co.uk>
+
+ * configure.in : New locations of QOF files and
+ postgres fix to clean up CFLAGS
+ * lib/Makefile.am : New directory.
+ * src/engine/Makefile.am : Remove QOF build
+ * src/backend/Makefile.am : Remove QSF directory.
+ * src/backend/postgres/test/Makefile.am : Build tests
+ without linking against the GModule to retain portability.
+ * src/import-export/qif-import/test/Makefile.am : Adjusted
+ linkage due to library changes.
+ * src/gnome-utils/test/Makefile.am : Adjusted linkage
+ due to library changes.
+
+ Moving QSF to lib/libqof/backend/file
+ * src/backend/qsf/qsf-backend.c
+ * src/backend/qsf/pilot-qsf-GnuCashInvoice.xml
+ * src/backend/qsf/qsf-dir.h.in
+ * src/backend/qsf/qsf-map.xsd.xml
+ * src/backend/qsf/qsf-xml-map.c
+ * src/backend/qsf/qof-backend-qsf.h
+ * src/backend/qsf/qsf-xml.c
+ * src/backend/qsf/Makefile.am
+ * src/backend/qsf/qsf-object.xsd.xml
+ * src/backend/qsf/qsf-xml.h :
+
+ Moving QOF to lib/libqof/qof/
+ * src/engine/qofbook-p.h
+ * src/engine/gnc-trace.c
+ * src/engine/qofquery-deserial.h
+ * src/engine/gnc-trace.h
+ * src/engine/gnc-date.c
+ * src/engine/qofquerycore-p.h
+ * src/engine/gnc-date.h
+ * src/engine/qofquery-serialize.c
+ * src/engine/qofid.c
+ * src/engine/qofquery-serialize.h
+ * src/engine/qofid.h
+ * src/engine/gnc-engine-util.c
+ * src/engine/gnc-event.c
+ * src/engine/qofgobj.c
+ * src/engine/gnc-engine-util.h
+ * src/engine/gnc-event.h
+ * src/engine/qofgobj.h
+ * src/engine/qofbook.c
+ * src/engine/qofchoice.c
+ * src/engine/qofbook.h
+ * src/engine/qofchoice.h
+ * src/engine/kvp_frame.c
+ * src/engine/qofquery.c
+ * src/engine/kvp_frame.h
+ * src/engine/qofquery.h
+ * src/engine/qofquerycore.c
+ * src/engine/qofquerycore.h
+ * src/engine/qofsession.c
+ * src/engine/qofsession-p.h
+ * src/engine/qofsession.h
+ * src/engine/qofid-p.h
+ * src/engine/qofsql.c
+ * src/engine/gnc-numeric.c
+ * src/engine/qofsql.h
+ * src/engine/gnc-numeric.h
+ * src/engine/kvp-util-p.h
+ * src/engine/qofclass-p.h
+ * src/engine/qof_book_merge.c
+ * src/engine/qof_book_merge.h
+ * src/engine/gnc-event-p.h
+ * src/engine/qofla-dir.h.in
+ * src/engine/qof.h
+ * src/engine/qofinstance.c
+ * src/engine/qofinstance.h
+ * src/engine/qofmath128.c
+ * src/engine/qofmath128.h
+ * src/engine/qofobject-p.h
+ * src/engine/Makefile.am
+ * src/engine/qofbackend.c
+ * src/engine/qofbackend-p.h
+ * src/engine/qofbackend.h
+ * src/engine/qofinstance-p.h
+ * src/engine/qofquery-p.h
+ * src/engine/md5.c
+ * src/engine/md5.h
+ * src/engine/kvp-util.c
+ * src/engine/qofclass.c
+ * src/engine/qof-be-utils.h
+ * src/engine/qofobject.c
+ * src/engine/kvp-util.h
+ * src/engine/qofclass.h
+ * src/engine/qofobject.h
+ * src/engine/guid.c
+ * src/engine/guid.h
+ * src/engine/qofquery-deserial.c :
+
2005-11-12 Christian Stimming <stimming at tuhh.de>
* src/*/*.glade: String improvements: Fix typos, remove
Modified: gnucash/trunk/configure.in
===================================================================
--- gnucash/trunk/configure.in 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/configure.in 2005-11-13 13:22:34 UTC (rev 11917)
@@ -415,11 +415,13 @@
fi
if test x$QOF_XML_DIR = x; then
AC_MSG_RESULT([no, will use internal QOF code])
- QOF_CFLAGS="-I\${top_srcdir}/src/engine"
- QOF_LIBS="\${top_srcdir}/src/engine/libqof.la"
- QOF_LIB_DIR="${libdir}"
+ QOF_LIB_DIR=`eval echo $libdir | sed "s%^NONE%$prefix%"`
+ QOF_LIB_DIR=`eval echo $QOF_LIB_DIR | sed "s%^NONE%$prefix%"`
+ QOF_CFLAGS="-I\${top_srcdir}/lib/libqof/qof"
+ QOF_LIBS="\${top_srcdir}/lib/libqof/qof/libqof.la"
+# QOF_LIB_DIR=`eval echo ${libdir}`
QOF_PREFIX="internal"
- QOF_XML_DIR="$QSF_SCHEMA_DIR"
+ QOF_XML_DIR=`eval echo ${datadir}/xml/qsf`
LIBQOF_LIBRARY_VERSION=1:1:0
LIBQOF_BACKEND_QSF_LIBRARY_VERSION=0:0:0
AC_SUBST(LIBQOF_LIBRARY_VERSION)
@@ -437,6 +439,7 @@
AS_SCRUB_INCLUDE(QOF_PREFIX)
AC_SUBST(QOF_PREFIX)
AC_SUBST(QOF_LIB_DIR)
+AC_SUBST(QOF_XML_DIR)
### --------------------------------------------------------------------------
### for GOG/goffice...
@@ -545,7 +548,6 @@
GNC_ACCOUNTS_DIR='${GNC_SHAREDIR}/accounts'
GNC_GLADE_DIR='${GNC_SHAREDIR}/glade'
-QSF_SCHEMA_DIR='${GNC_SHAREDIR}/xml/qsf'
GNC_UI_DIR='${GNC_SHAREDIR}/ui'
GNC_GWRAP_LIBDIR='${GNC_SHAREDIR}/guile-modules/g-wrapped'
GNC_MODULE_DIR='${pkglibdir}'
@@ -555,7 +557,6 @@
AC_SUBST(GNC_CONFIGDIR)
AC_SUBST(GNC_DOC_INSTALL_DIR)
AC_SUBST(GNC_GLADE_DIR)
-AC_SUBST(QSF_SCHEMA_DIR)
AC_SUBST(GNC_UI_DIR)
AC_SUBST(GNC_GWRAP_LIBDIR)
AC_SUBST(GNC_INCLUDE_DIR)
@@ -609,8 +610,9 @@
fi
AS_SCRUB_INCLUDE(PGSQL_CFLAGS)
-
+# XXX Fixme: CPPFLAGS are saved but CFLAGS are altered later on and not restored.
saved_CPPFLAGS="${CPPFLAGS}"
+ saved_CFLAGS="${CFLAGS}"
CPPFLAGS="${CPPFLAGS} ${PGSQL_CFLAGS}"
AC_CHECK_HEADERS(pgsql/libpq-fe.h postgresql/libpq-fe.h libpq-fe.h)
if test "x$ac_cv_header_pgsql_libpq_fe_h$ac_cv_header_postgresql_libpq_fe_h$ac_cv_header_libpq_fe_h" = xnonono; then
@@ -661,6 +663,7 @@
LIBS="$saved_LIBS"
fi
CPPFLAGS="$saved_CPPFLAGS"
+ CFLAGS="$saved_CFLAGS"
fi
]
)
@@ -1284,6 +1287,10 @@
lib/goffice/pixmaps/Makefile
lib/goffice/cut-n-paste/Makefile
lib/goffice/cut-n-paste/pcre/Makefile
+ lib/libqof/Makefile
+ lib/libqof/qof/Makefile
+ lib/libqof/backend/Makefile
+ lib/libqof/backend/file/Makefile
rpm/Makefile
src/Makefile
src/app-utils/Makefile
@@ -1294,7 +1301,6 @@
src/backend/file/test/Makefile
src/backend/file/test/test-files/Makefile
src/backend/file/test/test-files/xml2/Makefile
- src/backend/qsf/Makefile
src/backend/postgres/Makefile
src/backend/postgres/test/Makefile
src/backend/rpc/Makefile
Modified: gnucash/trunk/lib/Makefile.am
===================================================================
--- gnucash/trunk/lib/Makefile.am 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/lib/Makefile.am 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,7 +1,16 @@
+SUBDIRS = libc glib26 guile-www srfi
+
if USE_LIBGOFFICE
-SUBDIRS = libc glib26 guile-www srfi
+SUBDIRS +=
else
-SUBDIRS = libc glib26 guile-www srfi goffice
+SUBDIRS += goffice
endif
+if USE_LIBQOF
+SUBDIRS += libqof
+else
+SUBDIRS +=
+endif
+
EXTRA_DIST = README guppi-legend.patch
+
Property changes on: gnucash/trunk/lib/libqof
___________________________________________________________________
Name: svn:ignore
+ Makefile
Makefile.in
Added: gnucash/trunk/lib/libqof/Makefile.am
===================================================================
--- gnucash/trunk/lib/libqof/Makefile.am 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/lib/libqof/Makefile.am 2005-11-13 13:22:34 UTC (rev 11917)
@@ -0,0 +1,2 @@
+SUBDIRS = . qof backend
+
Property changes on: gnucash/trunk/lib/libqof/backend
___________________________________________________________________
Name: svn:ignore
+ Makefile
Makefile.in
Added: gnucash/trunk/lib/libqof/backend/Makefile.am
===================================================================
--- gnucash/trunk/lib/libqof/backend/Makefile.am 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/lib/libqof/backend/Makefile.am 2005-11-13 13:22:34 UTC (rev 11917)
@@ -0,0 +1,2 @@
+SUBDIRS = file
+
Property changes on: gnucash/trunk/lib/libqof/backend/file
___________________________________________________________________
Name: svn:ignore
+ qsf-dir.h
Makefile
Makefile.in
.libs
.deps
Added: gnucash/trunk/lib/libqof/backend/file/Makefile.am
===================================================================
--- gnucash/trunk/lib/libqof/backend/file/Makefile.am 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/lib/libqof/backend/file/Makefile.am 2005-11-13 13:22:34 UTC (rev 11917)
@@ -0,0 +1,43 @@
+SUBDIRS = .
+
+lib_LTLIBRARIES = libqof-backend-qsf.la
+
+AM_CFLAGS = \
+ -I.. -I../.. \
+ -DLOCALE_DIR=\""$(datadir)/locale"\" \
+ ${QOF_CFLAGS} \
+ ${LIBXML2_CFLAGS} \
+ ${GLIB_CFLAGS}
+
+libqof_backend_qsf_la_SOURCES = \
+ qsf-backend.c \
+ qsf-xml-map.c \
+ qsf-xml.c
+
+LIBADD = \
+ ${QOF_LIBS} \
+ ${GLIB_LIBS} \
+ ${LIBXML2_LIBS}
+
+qsfschemadir = $(QOF_XML_DIR)
+qsfschema_DATA = \
+ qsf-object.xsd.xml \
+ qsf-map.xsd.xml \
+ pilot-qsf-GnuCashInvoice.xml
+
+EXTRA_DIST = \
+ $(qsfschema_DATA) \
+ qsf-dir.h.in \
+ qof-backend-qsf.h \
+ qsf-xml.h
+
+qsf-dir.h: qsf-dir.h.in
+ rm -f $@.tmp
+ sed < $< > $@.tmp \
+ -e 's:@-QSF_SCHEMA_DIR-@:${QOF_XML_DIR}:g'
+ mv $@.tmp $@
+
+BUILT_SOURCES = qsf-dir.h
+
+CONFIG_CLEAN_FILES = qsf-dir.h
+
Copied: gnucash/trunk/lib/libqof/backend/file/pilot-qsf-GnuCashInvoice.xml (from rev 11885, gnucash/trunk/src/backend/qsf/pilot-qsf-GnuCashInvoice.xml)
Copied: gnucash/trunk/lib/libqof/backend/file/qof-backend-qsf.h (from rev 11885, gnucash/trunk/src/backend/qsf/qof-backend-qsf.h)
Copied: gnucash/trunk/lib/libqof/backend/file/qsf-backend.c (from rev 11885, gnucash/trunk/src/backend/qsf/qsf-backend.c)
Copied: gnucash/trunk/lib/libqof/backend/file/qsf-dir.h.in (from rev 11885, gnucash/trunk/src/backend/qsf/qsf-dir.h.in)
Copied: gnucash/trunk/lib/libqof/backend/file/qsf-map.xsd.xml (from rev 11885, gnucash/trunk/src/backend/qsf/qsf-map.xsd.xml)
Copied: gnucash/trunk/lib/libqof/backend/file/qsf-object.xsd.xml (from rev 11885, gnucash/trunk/src/backend/qsf/qsf-object.xsd.xml)
Copied: gnucash/trunk/lib/libqof/backend/file/qsf-xml-map.c (from rev 11885, gnucash/trunk/src/backend/qsf/qsf-xml-map.c)
Copied: gnucash/trunk/lib/libqof/backend/file/qsf-xml.c (from rev 11885, gnucash/trunk/src/backend/qsf/qsf-xml.c)
Copied: gnucash/trunk/lib/libqof/backend/file/qsf-xml.h (from rev 11885, gnucash/trunk/src/backend/qsf/qsf-xml.h)
Property changes on: gnucash/trunk/lib/libqof/qof
___________________________________________________________________
Name: svn:ignore
+ Makefile
Makefile.in
qofla-dir.h
.libs
.deps
libqof.la
Added: gnucash/trunk/lib/libqof/qof/Makefile.am
===================================================================
--- gnucash/trunk/lib/libqof/qof/Makefile.am 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/lib/libqof/qof/Makefile.am 2005-11-13 13:22:34 UTC (rev 11917)
@@ -0,0 +1,89 @@
+lib_LTLIBRARIES = libqof.la
+
+libqof_la_LDFLAGS= -version-info $(LIBQOF_LIBRARY_VERSION)
+
+AM_CFLAGS = \
+ -I. \
+ ${GLIB_CFLAGS}
+
+libqof_la_SOURCES = \
+ gnc-date.c \
+ gnc-engine-util.c \
+ gnc-numeric.c \
+ gnc-event.c \
+ gnc-trace.c \
+ guid.c \
+ kvp_frame.c \
+ kvp-util.c \
+ md5.c \
+ qofbackend.c \
+ qofclass.c \
+ qofchoice.c \
+ qofid.c \
+ qofinstance.c \
+ qofquery.c \
+ qofbook.c \
+ qofobject.c \
+ qofquerycore.c \
+ qofsession.c \
+ qof_book_merge.c
+
+qofincludedir = ${pkgincludedir}
+
+qofinclude_HEADERS = \
+ gnc-date.h \
+ gnc-engine-util.h \
+ gnc-numeric.h \
+ gnc-event.h \
+ gnc-trace.h \
+ guid.h \
+ kvp_frame.h \
+ kvp-util.h \
+ kvp-util-p.h \
+ qof.h \
+ qof-be-utils.h \
+ qofbackend.h \
+ qofbackend-p.h \
+ qofclass.h \
+ qofchoice.h \
+ qofgobj.h \
+ qofid.h \
+ qofid-p.h \
+ qofinstance-p.h \
+ qofinstance.h \
+ qofquery.h \
+ qofbook.h \
+ qofobject.h \
+ qofquerycore.h \
+ qofsession.h \
+ qofla-dir.h \
+ qof_book_merge.h
+
+noinst_HEADERS = \
+ gnc-event-p.h \
+ md5.h \
+ qofclass-p.h \
+ qofmath128.h \
+ qofquery-p.h \
+ qofquery-deserial.h \
+ qofquery-serialize.h \
+ qofbook-p.h \
+ qofobject-p.h \
+ qofquerycore-p.h \
+ qofsession-p.h
+
+QOFLIBdir = $(libdir)
+
+EXTRA_DIST = \
+ qofla-dir.h.in \
+ qofmath128.c
+
+qofla-dir.h: qofla-dir.h.in
+ rm -f $@.tmp
+ sed < $< > $@.tmp \
+ -e 's:@-libdir-@:${QOFLIBdir}:g'
+ mv $@.tmp $@
+
+BUILT_SOURCES = qofla-dir.h
+
+
Copied: gnucash/trunk/lib/libqof/qof/gnc-date.c (from rev 11885, gnucash/trunk/src/engine/gnc-date.c)
Copied: gnucash/trunk/lib/libqof/qof/gnc-date.h (from rev 11885, gnucash/trunk/src/engine/gnc-date.h)
Copied: gnucash/trunk/lib/libqof/qof/gnc-engine-util.c (from rev 11885, gnucash/trunk/src/engine/gnc-engine-util.c)
Copied: gnucash/trunk/lib/libqof/qof/gnc-engine-util.h (from rev 11885, gnucash/trunk/src/engine/gnc-engine-util.h)
Copied: gnucash/trunk/lib/libqof/qof/gnc-event-p.h (from rev 11885, gnucash/trunk/src/engine/gnc-event-p.h)
Copied: gnucash/trunk/lib/libqof/qof/gnc-event.c (from rev 11885, gnucash/trunk/src/engine/gnc-event.c)
Copied: gnucash/trunk/lib/libqof/qof/gnc-event.h (from rev 11885, gnucash/trunk/src/engine/gnc-event.h)
Copied: gnucash/trunk/lib/libqof/qof/gnc-numeric.c (from rev 11884, gnucash/trunk/src/engine/gnc-numeric.c)
Copied: gnucash/trunk/lib/libqof/qof/gnc-numeric.h (from rev 11884, gnucash/trunk/src/engine/gnc-numeric.h)
Copied: gnucash/trunk/lib/libqof/qof/gnc-trace.c (from rev 11885, gnucash/trunk/src/engine/gnc-trace.c)
Copied: gnucash/trunk/lib/libqof/qof/gnc-trace.h (from rev 11885, gnucash/trunk/src/engine/gnc-trace.h)
Copied: gnucash/trunk/lib/libqof/qof/guid.c (from rev 11885, gnucash/trunk/src/engine/guid.c)
Copied: gnucash/trunk/lib/libqof/qof/guid.h (from rev 11885, gnucash/trunk/src/engine/guid.h)
Copied: gnucash/trunk/lib/libqof/qof/kvp-util-p.h (from rev 11885, gnucash/trunk/src/engine/kvp-util-p.h)
Copied: gnucash/trunk/lib/libqof/qof/kvp-util.c (from rev 11885, gnucash/trunk/src/engine/kvp-util.c)
Copied: gnucash/trunk/lib/libqof/qof/kvp-util.h (from rev 11885, gnucash/trunk/src/engine/kvp-util.h)
Copied: gnucash/trunk/lib/libqof/qof/kvp_frame.c (from rev 11885, gnucash/trunk/src/engine/kvp_frame.c)
Copied: gnucash/trunk/lib/libqof/qof/kvp_frame.h (from rev 11885, gnucash/trunk/src/engine/kvp_frame.h)
Copied: gnucash/trunk/lib/libqof/qof/md5.c (from rev 11885, gnucash/trunk/src/engine/md5.c)
Copied: gnucash/trunk/lib/libqof/qof/md5.h (from rev 11885, gnucash/trunk/src/engine/md5.h)
Copied: gnucash/trunk/lib/libqof/qof/qof-be-utils.h (from rev 11885, gnucash/trunk/src/engine/qof-be-utils.h)
Copied: gnucash/trunk/lib/libqof/qof/qof.h (from rev 11885, gnucash/trunk/src/engine/qof.h)
Copied: gnucash/trunk/lib/libqof/qof/qof_book_merge.c (from rev 11885, gnucash/trunk/src/engine/qof_book_merge.c)
Copied: gnucash/trunk/lib/libqof/qof/qof_book_merge.h (from rev 11885, gnucash/trunk/src/engine/qof_book_merge.h)
Copied: gnucash/trunk/lib/libqof/qof/qofbackend-p.h (from rev 11885, gnucash/trunk/src/engine/qofbackend-p.h)
Copied: gnucash/trunk/lib/libqof/qof/qofbackend.c (from rev 11885, gnucash/trunk/src/engine/qofbackend.c)
Copied: gnucash/trunk/lib/libqof/qof/qofbackend.h (from rev 11885, gnucash/trunk/src/engine/qofbackend.h)
Copied: gnucash/trunk/lib/libqof/qof/qofbook-p.h (from rev 11885, gnucash/trunk/src/engine/qofbook-p.h)
Copied: gnucash/trunk/lib/libqof/qof/qofbook.c (from rev 11885, gnucash/trunk/src/engine/qofbook.c)
Copied: gnucash/trunk/lib/libqof/qof/qofbook.h (from rev 11885, gnucash/trunk/src/engine/qofbook.h)
Copied: gnucash/trunk/lib/libqof/qof/qofchoice.c (from rev 11885, gnucash/trunk/src/engine/qofchoice.c)
Copied: gnucash/trunk/lib/libqof/qof/qofchoice.h (from rev 11885, gnucash/trunk/src/engine/qofchoice.h)
Copied: gnucash/trunk/lib/libqof/qof/qofclass-p.h (from rev 11885, gnucash/trunk/src/engine/qofclass-p.h)
Copied: gnucash/trunk/lib/libqof/qof/qofclass.c (from rev 11885, gnucash/trunk/src/engine/qofclass.c)
Copied: gnucash/trunk/lib/libqof/qof/qofclass.h (from rev 11885, gnucash/trunk/src/engine/qofclass.h)
Copied: gnucash/trunk/lib/libqof/qof/qofgobj.c (from rev 11885, gnucash/trunk/src/engine/qofgobj.c)
Copied: gnucash/trunk/lib/libqof/qof/qofgobj.h (from rev 11885, gnucash/trunk/src/engine/qofgobj.h)
Copied: gnucash/trunk/lib/libqof/qof/qofid-p.h (from rev 11885, gnucash/trunk/src/engine/qofid-p.h)
Copied: gnucash/trunk/lib/libqof/qof/qofid.c (from rev 11885, gnucash/trunk/src/engine/qofid.c)
Copied: gnucash/trunk/lib/libqof/qof/qofid.h (from rev 11885, gnucash/trunk/src/engine/qofid.h)
Copied: gnucash/trunk/lib/libqof/qof/qofinstance-p.h (from rev 11885, gnucash/trunk/src/engine/qofinstance-p.h)
Copied: gnucash/trunk/lib/libqof/qof/qofinstance.c (from rev 11885, gnucash/trunk/src/engine/qofinstance.c)
Copied: gnucash/trunk/lib/libqof/qof/qofinstance.h (from rev 11885, gnucash/trunk/src/engine/qofinstance.h)
Copied: gnucash/trunk/lib/libqof/qof/qofla-dir.h.in (from rev 11885, gnucash/trunk/src/engine/qofla-dir.h.in)
Copied: gnucash/trunk/lib/libqof/qof/qofmath128.c (from rev 11885, gnucash/trunk/src/engine/qofmath128.c)
Copied: gnucash/trunk/lib/libqof/qof/qofmath128.h (from rev 11885, gnucash/trunk/src/engine/qofmath128.h)
Copied: gnucash/trunk/lib/libqof/qof/qofobject-p.h (from rev 11885, gnucash/trunk/src/engine/qofobject-p.h)
Copied: gnucash/trunk/lib/libqof/qof/qofobject.c (from rev 11885, gnucash/trunk/src/engine/qofobject.c)
Copied: gnucash/trunk/lib/libqof/qof/qofobject.h (from rev 11885, gnucash/trunk/src/engine/qofobject.h)
Copied: gnucash/trunk/lib/libqof/qof/qofquery-deserial.c (from rev 11885, gnucash/trunk/src/engine/qofquery-deserial.c)
Copied: gnucash/trunk/lib/libqof/qof/qofquery-deserial.h (from rev 11885, gnucash/trunk/src/engine/qofquery-deserial.h)
Copied: gnucash/trunk/lib/libqof/qof/qofquery-p.h (from rev 11885, gnucash/trunk/src/engine/qofquery-p.h)
Copied: gnucash/trunk/lib/libqof/qof/qofquery-serialize.c (from rev 11885, gnucash/trunk/src/engine/qofquery-serialize.c)
Copied: gnucash/trunk/lib/libqof/qof/qofquery-serialize.h (from rev 11885, gnucash/trunk/src/engine/qofquery-serialize.h)
Copied: gnucash/trunk/lib/libqof/qof/qofquery.c (from rev 11885, gnucash/trunk/src/engine/qofquery.c)
Copied: gnucash/trunk/lib/libqof/qof/qofquery.h (from rev 11885, gnucash/trunk/src/engine/qofquery.h)
Copied: gnucash/trunk/lib/libqof/qof/qofquerycore-p.h (from rev 11885, gnucash/trunk/src/engine/qofquerycore-p.h)
Copied: gnucash/trunk/lib/libqof/qof/qofquerycore.c (from rev 11885, gnucash/trunk/src/engine/qofquerycore.c)
Copied: gnucash/trunk/lib/libqof/qof/qofquerycore.h (from rev 11885, gnucash/trunk/src/engine/qofquerycore.h)
Copied: gnucash/trunk/lib/libqof/qof/qofsession-p.h (from rev 11885, gnucash/trunk/src/engine/qofsession-p.h)
Copied: gnucash/trunk/lib/libqof/qof/qofsession.c (from rev 11885, gnucash/trunk/src/engine/qofsession.c)
Copied: gnucash/trunk/lib/libqof/qof/qofsession.h (from rev 11885, gnucash/trunk/src/engine/qofsession.h)
Copied: gnucash/trunk/lib/libqof/qof/qofsql.c (from rev 11885, gnucash/trunk/src/engine/qofsql.c)
Copied: gnucash/trunk/lib/libqof/qof/qofsql.h (from rev 11885, gnucash/trunk/src/engine/qofsql.h)
Modified: gnucash/trunk/src/backend/Makefile.am
===================================================================
--- gnucash/trunk/src/backend/Makefile.am 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/backend/Makefile.am 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,10 +1,5 @@
-if USE_LIBQOF
-SUBDIRS = qsf file ${SQL_DIR} ${RPC_DIR}
-DIST_SUBDIRS = qsf file net postgres rpc
-else
SUBDIRS = file ${SQL_DIR} ${RPC_DIR}
-DIST_SUBDIRS = qsf file net postgres rpc
-endif
+DIST_SUBDIRS = file net postgres rpc
noinst_HEADERS = gnc-backend-api.h
Modified: gnucash/trunk/src/backend/postgres/test/Makefile.am
===================================================================
--- gnucash/trunk/src/backend/postgres/test/Makefile.am 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/backend/postgres/test/Makefile.am 2005-11-13 13:22:34 UTC (rev 11917)
@@ -29,9 +29,43 @@
${top_builddir}/src/engine/libgw-engine.la \
${top_builddir}/src/engine/libgw-kvp.la \
${top_builddir}/src/engine/test-core/libgncmod-test-engine.la \
- ${top_builddir}/src/backend/postgres/libgnc-backend-postgres.la \
- -lltdl
+ -lltdl \
+ -lpq
+test_db_SOURCES = \
+ ${top_srcdir}/src/backend/postgres/PostgresBackend.c \
+ ${top_srcdir}/src/backend/postgres/account.c \
+ ${top_srcdir}/src/backend/postgres/book.c \
+ ${top_srcdir}/src/backend/postgres/builder.c \
+ ${top_srcdir}/src/backend/postgres/checkpoint.c \
+ ${top_srcdir}/src/backend/postgres/escape.c \
+ ${top_srcdir}/src/backend/postgres/events.c \
+ ${top_srcdir}/src/backend/postgres/gncquery.c \
+ ${top_srcdir}/src/backend/postgres/kvp-sql.c \
+ ${top_srcdir}/src/backend/postgres/price.c \
+ ${top_srcdir}/src/backend/postgres/txn.c \
+ ${top_srcdir}/src/backend/postgres/txnmass.c \
+ ${top_srcdir}/src/backend/postgres/upgrade.c \
+ ${top_srcdir}/src/backend/postgres/putil.c \
+ test-db.c
+
+test_escape_SOURCES = \
+ ${top_srcdir}/src/backend/postgres/PostgresBackend.c \
+ ${top_srcdir}/src/backend/postgres/account.c \
+ ${top_srcdir}/src/backend/postgres/book.c \
+ ${top_srcdir}/src/backend/postgres/builder.c \
+ ${top_srcdir}/src/backend/postgres/checkpoint.c \
+ ${top_srcdir}/src/backend/postgres/escape.c \
+ ${top_srcdir}/src/backend/postgres/events.c \
+ ${top_srcdir}/src/backend/postgres/gncquery.c \
+ ${top_srcdir}/src/backend/postgres/kvp-sql.c \
+ ${top_srcdir}/src/backend/postgres/price.c \
+ ${top_srcdir}/src/backend/postgres/txn.c \
+ ${top_srcdir}/src/backend/postgres/txnmass.c \
+ ${top_srcdir}/src/backend/postgres/upgrade.c \
+ ${top_srcdir}/src/backend/postgres/putil.c \
+ test-escape.c
+
AM_CFLAGS = \
-I${top_srcdir}/src \
${QOF_CFLAGS} \
Modified: gnucash/trunk/src/backend/postgres/test/test-load-backend.c
===================================================================
--- gnucash/trunk/src/backend/postgres/test/test-load-backend.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/backend/postgres/test/test-load-backend.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -35,8 +35,10 @@
{
qof_init();
cashobjects_register();
+ /* the test needs to run locally in case make install
+ * has not yet been run. Use GNC_LIBDIR usually. */
do_test(
- qof_load_backend_library (QOF_LIB_DIR, PG_LIB_NAME, PG_LIB_INIT),
+ qof_load_backend_library ("../", PG_LIB_NAME, PG_LIB_INIT),
" loading gnc-backend-postgres GModule failed");
print_test_results();
qof_close();
Deleted: gnucash/trunk/src/backend/qsf/Makefile.am
===================================================================
--- gnucash/trunk/src/backend/qsf/Makefile.am 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/backend/qsf/Makefile.am 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,43 +0,0 @@
-SUBDIRS = .
-
-lib_LTLIBRARIES = libqof-backend-qsf.la
-
-AM_CFLAGS = \
- -I.. -I../.. \
- -I${top_srcdir}/src/backend \
- -I${top_srcdir}/src/engine \
- -DLOCALE_DIR=\""$(datadir)/locale"\" \
- -I${top_srcdir}/src/gnc-module \
- ${LIBXML2_CFLAGS} \
- ${GLIB_CFLAGS}
-
-libqof_backend_qsf_la_SOURCES = \
- qsf-backend.c \
- qsf-xml-map.c \
- qsf-xml.c
-
-LIBADD = \
- ${GLIB_LIBS} \
- ${LIBXML2_LIBS}
-
-qsfschemadir = $(QSF_SCHEMA_DIR)
-qsfschema_DATA = \
- qsf-object.xsd.xml \
- qsf-map.xsd.xml \
- pilot-qsf-GnuCashInvoice.xml
-
-EXTRA_DIST = \
- $(qsfschema_DATA) \
- qsf-dir.h.in \
- qof-backend-qsf.h \
- qsf-xml.h
-
-qsf-dir.h: qsf-dir.h.in
- rm -f $@.tmp
- sed < $< > $@.tmp \
- -e 's:@-QSF_SCHEMA_DIR-@:${QSF_SCHEMA_DIR}:g'
- mv $@.tmp $@
-
-BUILT_SOURCES = qsf-dir.h
-
-CONFIG_CLEAN_FILES = qsf-dir.h
Deleted: gnucash/trunk/src/backend/qsf/pilot-qsf-GnuCashInvoice.xml
===================================================================
--- gnucash/trunk/src/backend/qsf/pilot-qsf-GnuCashInvoice.xml 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/backend/qsf/pilot-qsf-GnuCashInvoice.xml 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,116 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- this map does NOT post invoices automatically -->
-<!-- maps use the same sequence of parameter types as other QSF -->
-<!-- Trans:desc can be set by expenses or datebook -->
-<qsf-map
-xmlns="http://qof.sourceforge.net/">
-<definition qof_version="3">
- <define e_type="pilot_expenses">Pilot-link QOF expenses</define>
- <define e_type="pilot_datebook">Pilot-link QOF datebook</define>
- <define e_type="pilot_address">Pilot-link QOF address</define>
- <define e_type="gncInvoice">Invoice</define>
- <define e_type="Trans">Transaction</define>
- <define e_type="gncEntry">Order/Invoice/Bill Entry</define>
- <default name="mileage_rate" type="numeric" value="28/100"/>
- <default name="use_weekday_descriptor" type="boolean" value="true"/>
- <default name="use_discount" type="boolean" value="false"/>
- <default name="tax_included" type="boolean" value="false"/>
- <default name="post_account" type="string" value="Assets:Current Assets:CD account"/>
- <default name="expenses_account" type="string" value="Income:Other Income"/>
- <default name="datebook_account" type="string" value="Income:Locum Income"/>
- <default name="tax_included" type="enum" value="1">GNC_TAXINCLUDED_YES</default>
- <default name="tax_included" type="enum" value="2">GNC_TAXINCLUDED_NO</default>
- <default name="tax_included" type="enum" value="3">GNC_TAXINCLUDED_USEGLOBAL</default>
- <default name="amount_type" type="enum" value="1">GNC_AMT_TYPE_VALUE</default>
- <default name="amount_type" type="enum" value="2">GNC_AMT_TYPE_PERCENT</default>
-</definition>
-<object type="gncEntry">
- <calculate type="string" value="desc">
- <if boolean="use_weekday_descriptor">
- <set format="%A">expense_date</set>
- </if>
- <else type="qof_expenses">
- <set>expense_vendor</set>
- </else>
- </calculate>
- <calculate type="string" value="action">
- <if type="qof-expenses">
- <set>Material</set>
- </if>
- <else type="qof-datebook">
- <set>Hours</set>
- </else>
- </calculate>
- <calculate type="string" value="notes">
- <set object="qof-expenses">expense_note</set>
- </calculate>
- <calculate type="guid" value="bill-to"/>
- <calculate type="boolean" value="invoice-taxable"/>
- <calculate type="boolean" value="bill-taxable"/>
- <calculate type="boolean" value="billable?"/>
- <calculate type="boolean" value="bill-tax-included"/>
- <calculate type="boolean" value="invoice-tax-included">
- <set>tax_included</set>
- </calculate>
- <calculate type="numeric" value="iprice">
- <if type="string" value="expense_type">
- <equals type="string" value="etMileage">
- <set>mileage_rate</set>
- </equals>
- </if>
- </calculate>
- <calculate type="numeric" value="bprice"/>
- <calculate type="numeric" value="qty">
- <if string="expense_type">
- <equals type="string" value="etMileage">
- <set object="qof-expenses">expense_amount</set>
- </equals>
- </if>
- <else type="string" value="expense_type">
- <set>0/1</set>
- </else>
- </calculate>
- <calculate type="numeric" value="invoice-discount">
- <set>0/1</set>
- </calculate>
- <calculate type="date" value="date-entered">
- <set>qsf_time_now</set>
- </calculate>
- <calculate type="date" value="date">
- <set>qsf_enquiry_date</set>
- </calculate>
- <calculate type="gint32" value="discount-type">
- <set option="amount_type_enum">GNC_AMT_TYPE_PERCENT</set>
- </calculate>
- <calculate type="gint32" value="discount-method">
- <set>2</set>
- </calculate>
- <calculate type="gint32" value="bill-payment-type"/>
-</object>
-<object type="Trans">
- <calculate type="string" value="num"/>
- <calculate type="string" value="desc"/>
- <calculate type="date" value="date-entered"/>
- <calculate type="date" value="date-posted"/>
- <calculate type="date" value="date-due"/>
- <calculate type="string" value="notes"/>
-</object>
-<object type="gncInvoice">
- <calculate type="string" value="id"/>
- <calculate type="string" value="billing_id"/>
- <calculate type="string" value="notes"/>
- <calculate type="guid" value="invoice_owner"/>
- <calculate type="guid" value="account"/>
- <calculate type="guid" value="posted_txn"/>
- <calculate type="guid" value="posted_lot"/>
- <calculate type="guid" value="terms"/>
- <calculate type="guid" value="bill-to"/>
- <calculate type="boolean" value="active">
- <set>true</set>
- </calculate>
- <calculate type="date" value="date_opened">
- <set>qsf_enquiry_date</set>
- </calculate>
- <calculate type="date" value="date_posted"/>
-</object>
-</qsf-map>
Deleted: gnucash/trunk/src/backend/qsf/qof-backend-qsf.h
===================================================================
--- gnucash/trunk/src/backend/qsf/qof-backend-qsf.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/backend/qsf/qof-backend-qsf.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,150 +0,0 @@
-/***************************************************************************
- * qof-backend-qsf.h
- *
- * Sat Jun 11 19:34:36 2005
- * Copyright 2005 Neil Williams
- * linux at codehelp.co.uk
- ****************************************************************************/
-/*
- * 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 Library General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/** @addtogroup Backend
- @{ */
-/** @addtogroup QSF QOF Serialisation Format
-
-This is the public interface of the qof-backend-qsf library.
-
-QSF - QOF Serialization Format is an XML serialization format
-i.e. it lays out a QOF object in a series of XML tags. The format will
-consist of two component formats:
-
-qof-qsf for the QSF object data and
-
-qsf-map to map sets of QSF objects between QOF applications.
-
-Maps exist to allow complex conversions between objects where object parameters
-need to be calculated, combined or processed using conditionals. Some QSF objects
-can be converted using XSL or other standard tools. For more information on maps,
-see http://code.neil.williamsleesmill.me.uk/map.html
-
-QSF object files will contain user data and are to be exported from QOF applications
-under user control or they can be hand-edited. QSF maps contain application data and
-can be created by application developers from application source code. Tools may be
-created later to generate maps interactively but maps require application support as
-well as an understanding of QOF objects in the import and output applications and are
-intended to remain within the scope of application developers rather than users.
-
-A QSF file written by one QOF application will need an appropriate QSF map before the
-data can be accessed by a different application using QOF. Any QSF objects that are
-not defined in the map will be ignored. QSF files written and accessed by the same
-application can use maps if necessary or can simply import the QSF data as a whole.
-
-Unless specifically mentioned otherwise, all defined strings are case-sensitive.
-
-Full documentation of this format is at:
-
-http://code.neil.williamsleesmill.me.uk/qsf.html
-
-QSF itself is now being built into the QOF library for use with pilot-link to allow
-Palm objects to be described in QOF, written to XML as QSF and imported directly into
-GnuCash and other QOF-compliant applications. As a generic format, it does not depend
-on any pre-defined objects - as the current GnuCash XML format depends on AccountGroup.
-Instead, QSF is a simple container for all QOF objects.
-
-QSF grew from the qof_book_merge code base and uses the qof_book_merge code that is now
-part of QOF. Any QofBook generated by QSF still needs to be merged into the existing
-application data using qof_book_merge. See ::BookMerge.
-
-QSF can be used as an export or offline storage format for QOF applications (although
-long term storage may be best performed using separate (non-XML) methods, depending
-on the application).
-
-QSF is designed to cope with partial QofBooks at the QofObject level. There is no
-requirement for specific objects to always be defined, as long as each QOF object
-specified is fully defined, no orphan or missing parameters are allowed. Part of the
-handling for partial books requires a storage mechanism for references to entities
-that are not within reach of the current book. This requires a little extra coding
-in the QSF QofBackend to contain the reference data so that when the book is
-written out, the reference can be included. When the file is imported back in, a
-little extra code then rebuilds those references during the merge.
-
-Copying entites from an existing QofBook using the qof_entity_copy routines will
-automatically create the reference table. If your QOF objects use references to other
-entities, books that are created manually also need to create a reference table.
-
-Work is continuing on supporting QSF in GnuCash and QOF. QSF is a very open format -
-the majority of the work will be in standardising object types and creating maps that
-convert between objects. Applications that read QSF should ignore any objects that do
-not match the available maps and warn the user about missing data.
-
-Anyone is free to create their own QSF objects, subject to the GNU GPL. It is intended
-that QSF can be used as the flexible, open and free format for QOF data - providing
-all that is lacking from a typical CSV export with all the validation benefits of XML
-and the complex data handling of QOF. The QSF object and map formats remain under the
-GNU GPL licence and QSF is free software.
-
-\todo
- - Adding more map support, some parts of the map are still not coded. equals,
- variables and the conditional logic may not be up to the task of the
- datebook repetition calculations.
- - Rationalise the API - remove functions that shouldn't be public.
-
-\todo QOF contains numerous g_string_sprintf and g_string_sprintfa calls.
- These are deprecated and should be renamed to g_string_printf and g_string_append_printf
- respectively.
-
-QSF is in three sections:
- - QSF Backend : a QofBackend for file:/ QSF objects and maps.
- qsf-backend.c
- - QSF Object : Input, export and validation of QSF object files.
- qsf-xml.c
- - QSF Map : Validation, processing and conversion routines.
- qsf-xml-map.c
-
- @{ */
-/** @file qof-backend-qsf.h
- @brief QSF API - Backend, maps and objects.
- @author Copyright (C) 2004-2005 Neil Williams <linux at codehelp.co.uk>
-*/
-
-#ifndef _QOF_BACKEND_QSF_H
-#define _QOF_BACKEND_QSF_H
-
-#include "gnc-trace.h"
-#include "qofbackend.h"
-#include "qof-be-utils.h"
-
-#define QOF_MOD_QSF "qof-backend-qsf"
-
-/** \brief Describe this backend to the application.
-
-Sets QSF Backend Version 0.1, access method = file:
-
-This is the QOF backend interface, not a GnuCash module.
-*/
-void qsf_provider_init(void);
-
-/** \brief Create a new QSF backend.
-
- Initialises the backend and provides access to the
- functions that will load and save the data.
-*/
-QofBackend* qsf_backend_new(void);
-
-/** @} */
-/** @} */
-
-#endif /* _QOF_BACKEND_QSF_H */
Deleted: gnucash/trunk/src/backend/qsf/qsf-backend.c
===================================================================
--- gnucash/trunk/src/backend/qsf/qsf-backend.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/backend/qsf/qsf-backend.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,1185 +0,0 @@
-/***************************************************************************
- * qsf-backend.c
- *
- * Sat Jan 1 15:07:14 2005
- * Copyright 2005 Neil Williams
- * linux at codehelp.co.uk
- ****************************************************************************/
-
-/*
- * 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 Library General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#define _GNU_SOURCE
-
-#include "qof-backend-qsf.h"
-#include "qsf-xml.h"
-#include "qsf-dir.h"
-#include <errno.h>
-#include <sys/stat.h>
-
-#define QSF_TYPE_BINARY "binary"
-#define QSF_TYPE_GLIST "glist"
-#define QSF_TYPE_FRAME "frame"
-#define QSF_COMPRESS "compression_level"
-
-static QofLogModule log_module = QOF_MOD_QSF;
-static int use_gz_level = 0;
-
-static void option_cb (QofBackendOption *option, gpointer data)
-{
- if(0 == safe_strcmp(QSF_COMPRESS, option->option_name)) {
- use_gz_level = *(gint*)option->value;
- }
-}
-
-static void
-qsf_load_config(QofBackend *be, KvpFrame *config)
-{
- qof_backend_option_foreach(config, option_cb, NULL);
-}
-
-static KvpFrame*
-qsf_get_config(QofBackend *be)
-{
- QofBackendOption *option;
-
- if(!be) { return NULL; }
- qof_backend_prepare_frame(be);
- option = g_new0(QofBackendOption, 1);
- option->option_name = QSF_COMPRESS;
- option->description = _("Level of compression to use: 0 for none, 9 for highest.");
- option->tooltip = _("QOF can compress QSF XML files using gzip. "
- "Note that compression is not used when outputting to STDOUT.");
- option->type = KVP_TYPE_GINT64;
- option->value = (gpointer)&use_gz_level;
- qof_backend_prepare_option(be, option);
- g_free(option);
- return qof_backend_complete_frame(be);
-}
-
-struct QSFBackend_s
-{
- QofBackend be;
- qsf_param *params;
- char *fullpath;
-};
-
-typedef struct QSFBackend_s QSFBackend;
-
-void
-qsf_param_init(qsf_param *params)
-{
- Timespec *qsf_ts;
- gchar qsf_time_string[QSF_DATE_LENGTH];
- gchar qsf_enquiry_date[QSF_DATE_LENGTH];
- gchar qsf_time_match[QSF_DATE_LENGTH];
- gchar qsf_time_now[QSF_DATE_LENGTH];
- time_t qsf_time_now_t;
- gchar *qsf_time_precision;
-
- g_return_if_fail(params != NULL);
- params->count = 0;
- params->supported_types = NULL;
- params->file_type = QSF_UNDEF;
- params->qsf_ns = NULL;
- params->output_doc = NULL;
- params->output_node = NULL;
- params->lister = NULL;
- params->map_ns = NULL;
- params->qsf_object_list = NULL;
- params->qsf_parameter_hash = g_hash_table_new(g_str_hash, g_str_equal);
- params->qsf_default_hash = g_hash_table_new(g_str_hash, g_str_equal);
- params->qsf_define_hash = g_hash_table_new(g_str_hash, g_str_equal);
- params->qsf_calculate_hash = g_hash_table_new(g_str_hash, g_str_equal);
- params->referenceList = NULL;
- params->supported_types = g_slist_append(params->supported_types, QOF_TYPE_STRING);
- params->supported_types = g_slist_append(params->supported_types, QOF_TYPE_GUID);
- params->supported_types = g_slist_append(params->supported_types, QOF_TYPE_BOOLEAN);
- params->supported_types = g_slist_append(params->supported_types, QOF_TYPE_NUMERIC);
- params->supported_types = g_slist_append(params->supported_types, QOF_TYPE_DATE);
- params->supported_types = g_slist_append(params->supported_types, QOF_TYPE_INT32);
- params->supported_types = g_slist_append(params->supported_types, QOF_TYPE_INT64);
- params->supported_types = g_slist_append(params->supported_types, QOF_TYPE_DOUBLE);
- params->supported_types = g_slist_append(params->supported_types, QOF_TYPE_CHAR);
- params->supported_types = g_slist_append(params->supported_types, QOF_TYPE_KVP);
- params->supported_types = g_slist_append(params->supported_types, QOF_TYPE_COLLECT);
- params->supported_types = g_slist_append(params->supported_types, QOF_TYPE_CHOICE);
- qsf_time_precision = "%j";
- qsf_time_now_t = time(NULL);
- qsf_ts = g_new(Timespec, 1);
- timespecFromTime_t(qsf_ts, qsf_time_now_t);
- strftime(qsf_enquiry_date, QSF_DATE_LENGTH, QSF_XSD_TIME, gmtime(&qsf_time_now_t));
- strftime(qsf_time_match, QSF_DATE_LENGTH, qsf_time_precision, gmtime(&qsf_time_now_t));
- strftime(qsf_time_string, QSF_DATE_LENGTH, "%F", gmtime(&qsf_time_now_t));
- strftime(qsf_time_now, QSF_DATE_LENGTH, QSF_XSD_TIME, gmtime(&qsf_time_now_t));
- g_hash_table_insert(params->qsf_default_hash, "qsf_enquiry_date", qsf_enquiry_date);
- g_hash_table_insert(params->qsf_default_hash, "qsf_time_now", &qsf_time_now_t);
- g_hash_table_insert(params->qsf_default_hash, "qsf_time_string", qsf_time_string);
-}
-
-static gboolean
-qsf_determine_file_type(const char *path)
-{
- struct stat sbuf;
-
- PINFO (" %s", path);
- if (!path) { return TRUE; }
- if (0 == safe_strcmp(path, QOF_STDOUT)) { return TRUE; }
- if (stat(path, &sbuf) <0) { return FALSE; }
- if (sbuf.st_size == 0) { return TRUE; }
- if(is_our_qsf_object(path)) { return TRUE; }
- else if(is_qsf_object(path)) { return TRUE; }
- else if(is_qsf_map(path)) { return TRUE; }
- return FALSE;
-}
-
-/* GnuCash does LOTS of filesystem work, QSF is going to leave most of it to libxml2. :-)
-Just strip the file: from the start of the book_path URL. Locks and file
-creation are not implemented.
-*/
-static void
-qsf_session_begin(QofBackend *be, QofSession *session, const char *book_path,
- gboolean ignore_lock, gboolean create_if_nonexistent)
-{
- QSFBackend *qsf_be;
- char *p, *path;
-
- PINFO (" ignore_lock=%d create_if_nonexistent=%d", ignore_lock, create_if_nonexistent);
- g_return_if_fail(be != NULL);
- qsf_be = (QSFBackend*)be;
- g_return_if_fail(qsf_be->params != NULL);
- qsf_be->fullpath = NULL;
- if(book_path == NULL)
- {
- qof_backend_set_error(be, ERR_BACKEND_NO_ERR);
- return;
- }
- p = strchr (book_path, ':');
- if (p) {
- path = g_strdup (book_path);
- if (!g_strncasecmp(path, "file:", 5)) {
- p = g_new(char, strlen(path) - 5 + 1);
- strcpy(p, path + 5);
- }
- qsf_be->fullpath = g_strdup(p);
- g_free (path);
- }
- else {
- qsf_be->fullpath = g_strdup(book_path);
- }
- qof_backend_set_error(be, ERR_BACKEND_NO_ERR);
-}
-
-static void
-qsf_session_end( QofBackend *be)
-{
- QSFBackend *qsf_be;
-
- qsf_be = (QSFBackend*)be;
- g_return_if_fail(qsf_be != NULL);
- qsf_free_params(qsf_be->params);
- g_free(qsf_be->fullpath);
- qsf_be->fullpath = NULL;
- xmlCleanupParser();
-}
-
-static void
-qsf_destroy_backend (QofBackend *be)
-{
- g_free(be);
-}
-
-QofBackendError
-qof_session_load_our_qsf_object(QofSession *first_session, const char *path)
-{
- QofSession *qsf_session;
-
- qsf_session = qof_session_new();
- qof_session_begin(qsf_session, path, FALSE, FALSE);
- qof_session_load(qsf_session, NULL);
- /* FIXME: This needs to return success and set the open not merge error in file_open */
- return ERR_QSF_OPEN_NOT_MERGE;
-}
-
-QofBackendError
-qof_session_load_qsf_object(QofSession *first_session, const char *path)
-{
- PINFO ("%s = ERR_QSF_NO_MAP", path);
- return ERR_QSF_NO_MAP;
-}
-
-void
-qsf_file_type(QofBackend *be, QofBook *book)
-{
- QSFBackend *qsf_be;
- qsf_param *params;
- char *path;
- gboolean result;
-
- g_return_if_fail(be != NULL);
- g_return_if_fail(book != NULL);
- qsf_be = (QSFBackend*) be;
- g_return_if_fail(qsf_be != NULL);
- g_return_if_fail(qsf_be->fullpath != NULL);
- g_return_if_fail(qsf_be->params != NULL);
- params = qsf_be->params;
- params->book = book;
- path = g_strdup(qsf_be->fullpath);
- params->filepath = g_strdup(path);
- qof_backend_get_error(be);
- result = is_our_qsf_object_be(params);
- if(result) {
- params->file_type = OUR_QSF_OBJ;
- result = load_our_qsf_object(book, path, params);
- if(!result) { qof_backend_set_error(be, ERR_FILEIO_PARSE_ERROR); }
- return;
- }
- else if(is_qsf_object_be(params)) {
- params->file_type = IS_QSF_OBJ;
- result = load_qsf_object(book, path, params);
- if(!result) { qof_backend_set_error(be, ERR_FILEIO_PARSE_ERROR); }
- }
- if(result == FALSE) {
- if(is_qsf_map_be(params)) {
- params->file_type = IS_QSF_MAP;
- qof_backend_set_error(be, ERR_QSF_MAP_NOT_OBJ);
- }
- }
-}
-
-static void
-ent_ref_cb (QofEntity* ent, gpointer user_data)
-{
- qsf_param *params;
- QofEntityReference *ref;
- void (*reference_setter) (QofEntity*, QofEntity*);
- QofEntity *reference;
- QofCollection *coll;
- QofIdType type;
-
- params = (qsf_param*)user_data;
- g_return_if_fail(params);
- while(params->referenceList)
- {
- ref = (QofEntityReference*)params->referenceList->data;
- if(qof_object_is_choice(ent->e_type)) { type = ref->choice_type; }
- else { type = ref->type; }
- coll = qof_book_get_collection(params->book, type);
- reference = qof_collection_lookup_entity(coll, ref->ref_guid);
- reference_setter = (void(*)(QofEntity*, QofEntity*))ref->param->param_setfcn;
- if(reference_setter != NULL)
- {
- qof_begin_edit((QofInstance*)ent);
- qof_begin_edit((QofInstance*)reference);
- reference_setter(ent, reference);
- qof_commit_edit((QofInstance*)ent);
- qof_commit_edit((QofInstance*)reference);
- }
- params->referenceList = g_list_next(params->referenceList);
- }
-}
-
-static void
-insert_ref_cb(QofObject *obj, gpointer user_data)
-{
- qsf_param *params;
-
- params = (qsf_param*)user_data;
- g_return_if_fail(params);
- qof_object_foreach(obj->e_type, params->book, ent_ref_cb, params);
-}
-
-/*================================================
- Load QofEntity into QofBook from XML in memory
-==================================================*/
-
-static gboolean
-qsfdoc_to_qofbook(xmlDocPtr doc, qsf_param *params)
-{
- QofInstance *inst;
- struct qsf_node_iterate iter;
- QofBook *book;
- GList *object_list;
- xmlNodePtr qsf_root;
- xmlNsPtr qsf_ns;
-
- g_return_val_if_fail(params != NULL, FALSE);
- g_return_val_if_fail(params->input_doc != NULL, FALSE);
- g_return_val_if_fail(params->book != NULL, FALSE);
- g_return_val_if_fail(params->file_type == OUR_QSF_OBJ, FALSE);
- qsf_root = xmlDocGetRootElement(params->input_doc);
- if(!qsf_root) { return FALSE; }
- qsf_ns = qsf_root->ns;
- iter.ns = qsf_ns;
- book = params->book;
- params->referenceList = (GList*)qof_book_get_data(book, ENTITYREFERENCE);
- qsf_node_foreach(qsf_root, qsf_book_node_handler, &iter, params);
- object_list = g_list_copy(params->qsf_object_list);
- while(object_list != NULL)
- {
- params->object_set = object_list->data;
- params->qsf_parameter_hash = params->object_set->parameters;
- inst = (QofInstance*)qof_object_new_instance(params->object_set->object_type, book);
- g_return_val_if_fail(inst != NULL, FALSE);
- params->qsf_ent = &inst->entity;
- qof_begin_edit(inst);
- g_hash_table_foreach(params->qsf_parameter_hash, qsf_object_commitCB, params);
- qof_commit_edit(inst);
- object_list = g_list_next(object_list);
- }
- qof_object_foreach_type(insert_ref_cb, params);
- qof_book_set_data(book, ENTITYREFERENCE, params->referenceList);
- return TRUE;
-}
-
-static void
-qsf_object_sequence(QofParam *qof_param, gpointer data)
-{
- qsf_param *params;
- GSList *checklist, *result;
-
- g_return_if_fail(data != NULL);
- params = (qsf_param*) data;
- result = NULL;
- checklist = NULL;
- params->knowntype = FALSE;
- checklist = g_slist_copy(params->supported_types);
- for(result = checklist; result != NULL; result = result->next)
- {
- if(0 == safe_strcmp((QofIdType)result->data, qof_param->param_type))
- {
- params->knowntype = TRUE;
- }
- }
- g_slist_free(checklist);
- if(0 == safe_strcmp(qof_param->param_type, params->qof_type))
- {
- params->qsf_sequence = g_slist_append(params->qsf_sequence, qof_param);
- params->knowntype = TRUE;
- }
- /* handle params->qof_type = QOF_TYPE_GUID and qof_param->param_type != known type */
- if(0 == safe_strcmp(params->qof_type, QOF_TYPE_GUID)
- && (params->knowntype == FALSE))
- {
- params->qsf_sequence = g_slist_append(params->qsf_sequence, qof_param);
- params->knowntype = TRUE;
- }
-}
-
-/* receives each entry from supported_types in sequence
- type = qof data type from supported list
- user_data = params. Holds object type
-*/
-static void
-qsf_supported_parameters(gpointer type, gpointer user_data)
-{
- qsf_param *params;
-
- g_return_if_fail(user_data != NULL);
- params = (qsf_param*) user_data;
- params->qof_type = (QofIdType)type;
- params->knowntype = FALSE;
- qof_class_param_foreach(params->qof_obj_type, qsf_object_sequence, params);
-}
-
-static KvpValueType
-qsf_to_kvp_helper(const char *type_string)
-{
- if(0 == safe_strcmp(QOF_TYPE_STRING, type_string)) { return KVP_TYPE_STRING; }
- if(0 == safe_strcmp(QOF_TYPE_GUID, type_string)) { return KVP_TYPE_GUID; }
- if(0 == safe_strcmp(QOF_TYPE_INT64, type_string)) { return KVP_TYPE_GINT64; }
- if(0 == safe_strcmp(QOF_TYPE_DOUBLE, type_string)) { return KVP_TYPE_DOUBLE; }
- if(0 == safe_strcmp(QOF_TYPE_NUMERIC, type_string)) { return KVP_TYPE_NUMERIC; }
- if(0 == safe_strcmp(QSF_TYPE_BINARY, type_string)) { return KVP_TYPE_BINARY; }
- if(0 == safe_strcmp(QSF_TYPE_GLIST, type_string)) { return KVP_TYPE_GLIST; }
- if(0 == safe_strcmp(QSF_TYPE_FRAME, type_string)) { return KVP_TYPE_FRAME; }
- return 0;
-}
-
-static void
-qsf_from_kvp_helper(const char *path, KvpValue *content, gpointer data)
-{
- qsf_param *params;
- QofParam *qof_param;
- xmlNodePtr node;
-
- params = (qsf_param*)data;
- qof_param = params->qof_param;
- g_return_if_fail(params && path && content);
- ENTER (" path=%s", path);
- switch(kvp_value_get_type(content))
- {
- case KVP_TYPE_STRING:
- {
- node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns,
- BAD_CAST qof_param->param_type));
- xmlNodeAddContent(node, BAD_CAST kvp_value_to_bare_string(content));
- xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, BAD_CAST path);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_VALUE, BAD_CAST QOF_TYPE_STRING);
- break;
- }
- case KVP_TYPE_GUID:
- {
- node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns,
- BAD_CAST qof_param->param_type));
- xmlNodeAddContent(node, BAD_CAST kvp_value_to_bare_string(content));
- xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, BAD_CAST path);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_VALUE, BAD_CAST QOF_TYPE_GUID);
- break;
- }
- case KVP_TYPE_BINARY:
- {
- node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns,
- BAD_CAST qof_param->param_type));
- xmlNodeAddContent(node, BAD_CAST kvp_value_to_bare_string(content));
- xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, BAD_CAST path);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_VALUE, BAD_CAST QSF_TYPE_BINARY);
- break;
- }
- case KVP_TYPE_GLIST:
- {
- node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns,
- BAD_CAST qof_param->param_type));
- xmlNodeAddContent(node, BAD_CAST kvp_value_to_bare_string(content));
- xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, BAD_CAST path);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_VALUE, BAD_CAST QSF_TYPE_GLIST);
- break;
- }
- case KVP_TYPE_FRAME:
- {
- node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns,
- BAD_CAST qof_param->param_type));
- xmlNodeAddContent(node, BAD_CAST kvp_value_to_bare_string(content));
- xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, BAD_CAST path);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_VALUE, BAD_CAST QSF_TYPE_FRAME);
- break;
- }
- case KVP_TYPE_GINT64:
- {
- node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns,
- BAD_CAST qof_param->param_type));
- xmlNodeAddContent(node, BAD_CAST kvp_value_to_bare_string(content));
- xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, BAD_CAST path);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_VALUE, BAD_CAST QOF_TYPE_INT64);
- break;
- }
- case KVP_TYPE_DOUBLE:
- {
- node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns,
- BAD_CAST qof_param->param_type));
- xmlNodeAddContent(node, BAD_CAST kvp_value_to_bare_string(content));
- xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, BAD_CAST path);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_VALUE, BAD_CAST QOF_TYPE_DOUBLE);
- break;
- }
- case KVP_TYPE_NUMERIC:
- {
- node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns,
- BAD_CAST qof_param->param_type));
- xmlNodeAddContent(node, BAD_CAST kvp_value_to_bare_string(content));
- xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_KVP, BAD_CAST path);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_VALUE, BAD_CAST QOF_TYPE_NUMERIC);
- break;
- }
- default:
- { break; }
- }
- LEAVE (" ");
-}
-
-static void
-qsf_from_coll_cb (QofEntity *ent, gpointer user_data)
-{
- qsf_param *params;
- QofParam *qof_param;
- xmlNodePtr node;
- gchar qsf_guid[GUID_ENCODING_LENGTH + 1];
-
- params = (qsf_param*)user_data;
- if(!ent || !params) { return; }
- qof_param = params->qof_param;
- node = xmlAddChild(params->output_node, xmlNewNode(params->qsf_ns,
- BAD_CAST qof_param->param_type));
- guid_to_string_buff(qof_entity_get_guid(ent), qsf_guid);
- xmlNodeAddContent(node, BAD_CAST qsf_guid);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
-}
-
-/******* reference handling ***********/
-
-static gint
-qof_reference_list_cb(gconstpointer a, gconstpointer b)
-{
- const QofEntityReference *aa;
- const QofEntityReference *bb;
-
- aa = (QofEntityReference*) a;
- bb = (QofEntityReference*) b;
- if(aa == NULL) { return 1; }
- g_return_val_if_fail((bb != NULL), 1);
- g_return_val_if_fail((aa->type != NULL), 1);
- if((0 == guid_compare(bb->ent_guid, aa->ent_guid))
- &&(0 == safe_strcmp(bb->type, aa->type))
- &&(0 == safe_strcmp(bb->param->param_name, aa->param->param_name)))
- {
- return 0;
- }
- return 1;
-}
-
-static QofEntityReference*
-qof_reference_lookup(GList *referenceList, QofEntityReference *find)
-{
- GList *single_ref;
- QofEntityReference *ent_ref;
-
- if(referenceList == NULL) { return NULL; }
- g_return_val_if_fail(find != NULL, NULL);
- single_ref = NULL;
- ent_ref = NULL;
- single_ref = g_list_find_custom(referenceList, find, qof_reference_list_cb);
- if(single_ref == NULL) { return ent_ref; }
- ent_ref = (QofEntityReference*)single_ref->data;
- g_list_free(single_ref);
- return ent_ref;
-}
-
-static void
-reference_list_lookup(gpointer data, gpointer user_data)
-{
- QofEntity *ent;
- QofParam *ref_param;
- QofEntityReference *reference, *starter;
- qsf_param *params;
- xmlNodePtr node, object_node;
- xmlNsPtr ns;
- GList *copy_list;
- gchar qsf_guid[GUID_ENCODING_LENGTH + 1], *ref_name;
-
- params = (qsf_param*)user_data;
- ref_param = (QofParam*)data;
- object_node = params->output_node;
- ent = params->qsf_ent;
- ns = params->qsf_ns;
- starter = g_new(QofEntityReference, 1);
- starter->ent_guid = qof_entity_get_guid(ent);
- starter->type = g_strdup(ent->e_type);
- starter->param = ref_param;
- starter->ref_guid = NULL;
- copy_list = g_list_copy(params->referenceList);
- reference = qof_reference_lookup(copy_list, starter);
- g_free(starter);
- if(reference != NULL) {
- if((ref_param->param_getfcn == NULL)||(ref_param->param_setfcn == NULL))
- {
- return;
- }
- ref_name = g_strdup(reference->param->param_name);
- node = xmlAddChild(object_node, xmlNewNode(ns, BAD_CAST QOF_TYPE_GUID));
- guid_to_string_buff(reference->ref_guid, qsf_guid);
- xmlNodeAddContent(node, BAD_CAST qsf_guid);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST ref_name);
- g_free(ref_name);
- }
-}
-
-/*=====================================
- Convert QofEntity to QSF XML node
-qof_param holds the parameter sequence.
-=======================================*/
-static void
-qsf_entity_foreach(QofEntity *ent, gpointer data)
-{
- qsf_param *params;
- GSList *param_list, *supported;
- GList *ref;
- xmlNodePtr node, object_node;
- xmlNsPtr ns;
- gchar *string_buffer;
- GString *buffer;
- QofParam *qof_param;
- QofEntity *choice_ent;
- KvpFrame *qsf_kvp;
- QofCollection *qsf_coll;
- int param_count;
- gboolean own_guid;
- const GUID *cm_guid;
- char cm_sa[GUID_ENCODING_LENGTH + 1];
-
- g_return_if_fail(data != NULL);
- params = (qsf_param*)data;
- param_count = ++params->count;
- ns = params->qsf_ns;
- qsf_kvp = kvp_frame_new();
- own_guid = FALSE;
- choice_ent = NULL;
- object_node = xmlNewChild(params->book_node, params->qsf_ns,
- BAD_CAST QSF_OBJECT_TAG, NULL);
- xmlNewProp(object_node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST ent->e_type);
- buffer = g_string_new(" ");
- g_string_printf(buffer, "%i", param_count);
- xmlNewProp(object_node, BAD_CAST QSF_OBJECT_COUNT, BAD_CAST buffer->str);
- param_list = g_slist_copy(params->qsf_sequence);
- while(param_list != NULL) {
- qof_param = (QofParam*)param_list->data;
- g_return_if_fail(qof_param != NULL);
- if(0 == safe_strcmp(qof_param->param_type, QOF_TYPE_GUID))
- {
- if(!own_guid)
- {
- cm_guid = qof_entity_get_guid(ent);
- node = xmlAddChild(object_node, xmlNewNode(ns, BAD_CAST QOF_TYPE_GUID));
- guid_to_string_buff(cm_guid, cm_sa);
- string_buffer = g_strdup(cm_sa);
- xmlNodeAddContent(node, BAD_CAST string_buffer);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE , BAD_CAST QOF_PARAM_GUID);
- own_guid = TRUE;
- }
- params->qsf_ent = ent;
- params->output_node = object_node;
- ref = qof_class_get_referenceList(ent->e_type);
- if(ref != NULL) {
- g_list_foreach(ref, reference_list_lookup, params);
- }
- }
- if(0 == safe_strcmp(qof_param->param_type, QOF_TYPE_COLLECT))
- {
- qsf_coll = qof_param->param_getfcn(ent, qof_param);
- params->qof_param = qof_param;
- params->output_node = object_node;
- qof_collection_foreach(qsf_coll, qsf_from_coll_cb, params);
- }
- if(0 == safe_strcmp(qof_param->param_type, QOF_TYPE_CHOICE))
- {
- /** \todo use the reference list here. */
- /* repeats due to use of reference list for GUID and CHOICE */
- /* fix to allow COLLECT too */
- choice_ent = (QofEntity*)qof_param->param_getfcn(ent, qof_param);
- if(!choice_ent) {
- param_list = g_slist_next(param_list);
- continue;
- }
- node = xmlAddChild(object_node, xmlNewNode(ns, BAD_CAST qof_param->param_type));
- cm_guid = qof_entity_get_guid(choice_ent);
- guid_to_string_buff(cm_guid, cm_sa);
- string_buffer = g_strdup(cm_sa);
- xmlNodeAddContent(node, BAD_CAST string_buffer);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
- xmlNewProp(node, BAD_CAST "name", BAD_CAST choice_ent->e_type);
- param_list = g_slist_next(param_list);
- continue;
- }
- if(0 == safe_strcmp(qof_param->param_type, QOF_TYPE_KVP))
- {
- qsf_kvp = kvp_frame_copy(qof_param->param_getfcn(ent,qof_param));
- params->qof_param = qof_param;
- params->output_node = object_node;
- kvp_frame_for_each_slot(qsf_kvp, qsf_from_kvp_helper, params);
- }
- if((qof_param->param_setfcn != NULL) && (qof_param->param_getfcn != NULL))
- {
- for( supported = g_slist_copy(params->supported_types);
- supported != NULL; supported = g_slist_next(supported))
- {
- if(0 == safe_strcmp((const char*)supported->data, (const char*)qof_param->param_type))
- {
- node = xmlAddChild(object_node, xmlNewNode(ns, BAD_CAST qof_param->param_type));
- string_buffer = g_strdup(qof_book_merge_param_as_string(qof_param, ent));
- xmlNodeAddContent(node, BAD_CAST string_buffer);
- xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST qof_param->param_name);
- }
- }
- }
- param_list = g_slist_next(param_list);
- }
-}
-
-static void
-qsf_foreach_obj_type(QofObject *qsf_obj, gpointer data)
-{
- qsf_param *params;
- QofBook *book;
- GSList *support;
-
- g_return_if_fail(data != NULL);
- params = (qsf_param*) data;
- /* Skip unsupported objects */
- if((qsf_obj->create == NULL)||(qsf_obj->foreach == NULL)){
- PINFO (" qsf_obj QOF support failed %s", qsf_obj->e_type);
- return;
- }
- params->qof_obj_type = qsf_obj->e_type;
- params->qsf_sequence = NULL;
- book = params->book;
- support = g_slist_copy(params->supported_types);
- g_slist_foreach(support,qsf_supported_parameters, params);
- qof_object_foreach(qsf_obj->e_type, book, qsf_entity_foreach, params);
-}
-
-/*=====================================================
- Take a QofBook and prepare a QSF XML doc in memory
-=======================================================*/
-/* QSF only uses one QofBook per file - count may be removed later. */
-static xmlDocPtr
-qofbook_to_qsf(QofBook *book, qsf_param *params)
-{
- xmlNodePtr top_node, node;
- xmlDocPtr doc;
- gchar buffer[GUID_ENCODING_LENGTH + 1];
- const GUID *book_guid;
-
- g_return_val_if_fail(book != NULL, NULL);
- params->book = book;
- params->referenceList = g_list_copy((GList*)qof_book_get_data(book, ENTITYREFERENCE));
- doc = xmlNewDoc(BAD_CAST QSF_XML_VERSION);
- top_node = xmlNewNode(NULL, BAD_CAST QSF_ROOT_TAG);
- xmlDocSetRootElement(doc, top_node);
- xmlSetNs(top_node, xmlNewNs(top_node, BAD_CAST QSF_DEFAULT_NS, NULL));
- params->qsf_ns = top_node->ns;
- node = xmlNewChild(top_node, params->qsf_ns, BAD_CAST QSF_BOOK_TAG, NULL);
- params->book_node = node;
- xmlNewProp(node, BAD_CAST QSF_BOOK_COUNT, BAD_CAST "1");
- book_guid = qof_book_get_guid(book);
- guid_to_string_buff(book_guid, buffer);
- xmlNewChild(params->book_node, params->qsf_ns, BAD_CAST QSF_BOOK_GUID, BAD_CAST buffer);
- params->output_doc = doc;
- params->book_node = node;
- qof_object_foreach_type(qsf_foreach_obj_type, params);
- return params->output_doc;
-}
-
-static void
-write_qsf_from_book(const char *path, QofBook *book, qsf_param *params)
-{
- xmlDocPtr qsf_doc;
- gint write_result;
- QofBackend *be;
-
- be = qof_book_get_backend(book);
- qsf_doc = qofbook_to_qsf(book, params);
- write_result = 0;
- if((use_gz_level > 0) && (use_gz_level <= 9))
- {
- xmlSetDocCompressMode(qsf_doc, use_gz_level);
- }
- g_return_if_fail(qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, qsf_doc) == TRUE);
- write_result = xmlSaveFormatFileEnc(path, qsf_doc, "UTF-8", 1);
- if(write_result < 0)
- {
- qof_backend_set_error(be, ERR_FILEIO_WRITE_ERROR);
- return;
- }
- xmlFreeDoc(qsf_doc);
-}
-
-static void
-write_qsf_to_stdout(QofBook *book, qsf_param *params)
-{
- xmlDocPtr qsf_doc;
-
- qsf_doc = qofbook_to_qsf(book, params);
- g_return_if_fail(qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, qsf_doc) == TRUE);
- xmlSaveFormatFileEnc("-", qsf_doc, "UTF-8", 1);
- fprintf(stdout, "\n");
- xmlFreeDoc(qsf_doc);
- LEAVE (" ");
-}
-
-void
-qsf_write_file(QofBackend *be, QofBook *book)
-{
- QSFBackend *qsf_be;
- qsf_param *params;
- char *path;
-
- qsf_be = (QSFBackend*)be;
- params = qsf_be->params;
- /* if fullpath is blank, book_id was set to QOF_STDOUT */
- if (!qsf_be->fullpath || (*qsf_be->fullpath == '\0')) {
- write_qsf_to_stdout(book, params);
- return;
- }
- path = strdup(qsf_be->fullpath);
- write_qsf_from_book(path, book, params);
- g_free(path);
-}
-
-/* QofBackend routine to load from file - needs a map.
-*/
-gboolean
-load_qsf_object(QofBook *book, const char *fullpath, qsf_param *params)
-{
- xmlNodePtr qsf_root, map_root;
- xmlDocPtr mapDoc, foreign_doc;
- gchar *map_path, *map_file;
-
- map_file = g_strdup("pilot-qsf-GnuCashInvoice.xml");
- foreign_doc = xmlParseFile(fullpath);
- if (foreign_doc == NULL) {
- qof_backend_set_error(params->be, ERR_FILEIO_PARSE_ERROR);
- return FALSE;
- }
- qsf_root = NULL;
- qsf_root = xmlDocGetRootElement(foreign_doc);
- params->qsf_ns = qsf_root->ns;
- params->book = book;
- map_path = g_strdup_printf("%s/%s", QSF_SCHEMA_DIR, map_file);
- if(map_path == NULL) { return FALSE; }
- mapDoc = xmlParseFile(map_path);
- map_root = xmlDocGetRootElement(mapDoc);
- params->map_ns = map_root->ns;
- params->input_doc = qsf_object_convert(mapDoc, qsf_root, params);
- qsfdoc_to_qofbook(params->input_doc, params);
- return TRUE;
-}
-
-gboolean
-load_our_qsf_object(QofBook *book, const char *fullpath, qsf_param *params)
-{
- xmlNodePtr qsf_root;
-
- params->input_doc = xmlParseFile(fullpath);
- if (params->input_doc == NULL) {
- qof_backend_set_error(params->be, ERR_FILEIO_PARSE_ERROR);
- return FALSE;
- }
- qsf_root = NULL;
- qsf_root = xmlDocGetRootElement(params->input_doc);
- params->qsf_ns = qsf_root->ns;
- return qsfdoc_to_qofbook(params->input_doc, params);
-}
-
-KvpValue*
-string_to_kvp_value(const char *content, KvpValueType type)
-{
- char *tail;
- gint64 cm_i64;
- double cm_double;
- gnc_numeric cm_numeric;
- GUID *cm_guid;
- struct tm kvp_time;
- time_t kvp_time_t;
- Timespec cm_date;
-
- switch(type) {
- case KVP_TYPE_GINT64:
- errno = 0;
- cm_i64 = strtoll(content, &tail, 0);
- if(errno == 0) {
- return kvp_value_new_gint64(cm_i64);
- }
- break;
- case KVP_TYPE_DOUBLE:
- errno = 0;
- cm_double = strtod(content, &tail);
- if(errno == 0) {
- return kvp_value_new_double(cm_double);
- }
- break;
- case KVP_TYPE_NUMERIC:
- string_to_gnc_numeric(content, &cm_numeric);
- return kvp_value_new_gnc_numeric(cm_numeric);
- break;
- case KVP_TYPE_STRING:
- return kvp_value_new_string(content);
- break;
- case KVP_TYPE_GUID:
- cm_guid = g_new(GUID, 1);
- if(TRUE == string_to_guid(content, cm_guid))
- {
- return kvp_value_new_guid(cm_guid);
- }
- break;
- case KVP_TYPE_TIMESPEC:
- strptime(content, QSF_XSD_TIME, &kvp_time);
- kvp_time_t = mktime(&kvp_time);
- timespecFromTime_t(&cm_date, kvp_time_t);
- return kvp_value_new_timespec(cm_date);
- break;
- case KVP_TYPE_BINARY:
-// return kvp_value_new_binary(value->value.binary.data,
-// value->value.binary.datasize);
- break;
- case KVP_TYPE_GLIST:
-// return kvp_value_new_glist(value->value.list);
- break;
- case KVP_TYPE_FRAME:
-// return kvp_value_new_frame(value->value.frame);
- break;
- }
- return NULL;
-}
-
-/*======================================================
- Commit XML data from file to QofEntity in a QofBook
-========================================================*/
-void
-qsf_object_commitCB(gpointer key, gpointer value, gpointer data)
-{
- qsf_param *params;
- qsf_objects *object_set;
- xmlNodePtr node;
- QofEntityReference *reference;
- QofEntity *qsf_ent;
- QofBook *targetBook;
- const char *qof_type, *parameter_name, *timechk;
- QofIdType obj_type, reference_type;
- struct tm qsf_time;
- time_t qsf_time_t;
- char *tail;
- /* cm_ prefix used for variables that hold the data to commit */
- gnc_numeric cm_numeric;
- double cm_double;
- gboolean cm_boolean;
- gint32 cm_i32;
- gint64 cm_i64;
- Timespec cm_date;
- char cm_char, (*char_getter) (xmlNodePtr);
- GUID *cm_guid;
- KvpFrame *cm_kvp;
- KvpValue *cm_value;
- KvpValueType cm_type;
- QofSetterFunc cm_setter;
- const QofParam *cm_param;
- void (*string_setter) (QofEntity*, const char*);
- void (*date_setter) (QofEntity*, Timespec);
- void (*numeric_setter) (QofEntity*, gnc_numeric);
- void (*double_setter) (QofEntity*, double);
- void (*boolean_setter) (QofEntity*, gboolean);
- void (*i32_setter) (QofEntity*, gint32);
- void (*i64_setter) (QofEntity*, gint64);
- void (*char_setter) (QofEntity*, char);
- void (*kvp_frame_setter) (QofEntity*, KvpFrame*);
-
- g_return_if_fail(data != NULL);
- g_return_if_fail(value != NULL);
- params = (qsf_param*)data;
- node = (xmlNodePtr)value;
- parameter_name = (const char*)key;
- qof_type = (char*)node->name;
- qsf_ent = params->qsf_ent;
- targetBook = params->book;
- memset (&qsf_time, '\0', sizeof(qsf_time));
- cm_date.tv_nsec = 0;
- cm_date.tv_sec = 0;
- obj_type = (char*)xmlGetProp(node->parent, BAD_CAST QSF_OBJECT_TYPE);
- if(0 == safe_strcasecmp(obj_type, parameter_name)) { return; }
- cm_setter = qof_class_get_parameter_setter(obj_type, parameter_name);
- cm_param = qof_class_get_parameter(obj_type, parameter_name);
- object_set = params->object_set;
- if(safe_strcmp(qof_type, QOF_TYPE_STRING) == 0) {
- string_setter = (void(*)(QofEntity*, const char*))cm_setter;
- if(string_setter != NULL) { string_setter(qsf_ent, (char*)xmlNodeGetContent(node)); }
- }
- if(safe_strcmp(qof_type, QOF_TYPE_DATE) == 0) {
- date_setter = (void(*)(QofEntity*, Timespec))cm_setter;
- timechk = NULL;
- timechk = strptime((char*)xmlNodeGetContent(node), QSF_XSD_TIME, &qsf_time);
- g_return_if_fail(timechk != NULL);
- qsf_time_t = mktime(&qsf_time);
- timespecFromTime_t(&cm_date, qsf_time_t);
- if(date_setter != NULL) { date_setter(qsf_ent, cm_date); }
- }
- if((safe_strcmp(qof_type, QOF_TYPE_NUMERIC) == 0) ||
- (safe_strcmp(qof_type, QOF_TYPE_DEBCRED) == 0)) {
- numeric_setter = (void(*)(QofEntity*, gnc_numeric))cm_setter;
- string_to_gnc_numeric((char*)xmlNodeGetContent(node), &cm_numeric);
- if(numeric_setter != NULL) { numeric_setter(qsf_ent, cm_numeric); }
- }
- if(safe_strcmp(qof_type, QOF_TYPE_GUID) == 0) {
- cm_guid = g_new(GUID, 1);
- if(TRUE != string_to_guid((char*)xmlNodeGetContent(node), cm_guid))
- {
- qof_backend_set_error(params->be, ERR_QSF_BAD_OBJ_GUID);
- PINFO (" string to guid conversion failed for %s:%s:%s",
- xmlNodeGetContent(node), obj_type, qof_type);
- return;
- }
- reference_type = (char*)xmlGetProp(node, BAD_CAST QSF_OBJECT_TYPE);
- if(0 == safe_strcmp(QOF_PARAM_GUID, reference_type))
- {
- qof_entity_set_guid(qsf_ent, cm_guid);
- }
- else {
- reference = qof_entity_get_reference_from(qsf_ent, cm_param);
- if(reference) {
- params->referenceList = g_list_append(params->referenceList, reference);
- }
- }
- }
- if(safe_strcmp(qof_type, QOF_TYPE_INT32) == 0) {
- errno = 0;
- cm_i32 = (gint32)strtol ((char*)xmlNodeGetContent(node), &tail, 0);
- if(errno == 0) {
- i32_setter = (void(*)(QofEntity*, gint32))cm_setter;
- if(i32_setter != NULL) { i32_setter(qsf_ent, cm_i32); }
- }
- else { qof_backend_set_error(params->be, ERR_QSF_OVERFLOW); }
- }
- if(safe_strcmp(qof_type, QOF_TYPE_INT64) == 0) {
- errno = 0;
- cm_i64 = strtoll((char*)xmlNodeGetContent(node), &tail, 0);
- if(errno == 0) {
- i64_setter = (void(*)(QofEntity*, gint64))cm_setter;
- if(i64_setter != NULL) { i64_setter(qsf_ent, cm_i64); }
- }
- else { qof_backend_set_error(params->be, ERR_QSF_OVERFLOW); }
- }
- if(safe_strcmp(qof_type, QOF_TYPE_DOUBLE) == 0) {
- errno = 0;
- cm_double = strtod((char*)xmlNodeGetContent(node), &tail);
- if(errno == 0) {
- double_setter = (void(*)(QofEntity*, double))cm_setter;
- if(double_setter != NULL) { double_setter(qsf_ent, cm_double); }
- }
- }
- if(safe_strcmp(qof_type, QOF_TYPE_BOOLEAN) == 0){
- if(0 == safe_strcasecmp((char*)xmlNodeGetContent(node), QSF_XML_BOOLEAN_TEST)) {
- cm_boolean = TRUE;
- }
- else { cm_boolean = FALSE; }
- boolean_setter = (void(*)(QofEntity*, gboolean))cm_setter;
- if(boolean_setter != NULL) { boolean_setter(qsf_ent, cm_boolean); }
- }
- if(safe_strcmp(qof_type, QOF_TYPE_KVP) == 0) {
- cm_type = qsf_to_kvp_helper((char*)xmlGetProp(node, BAD_CAST QSF_OBJECT_VALUE));
- if(!cm_type) { return; }
- cm_value = string_to_kvp_value((char*)xmlNodeGetContent(node), cm_type);
- cm_kvp = kvp_frame_copy(cm_param->param_getfcn(qsf_ent, cm_param));
- cm_kvp = kvp_frame_set_value(cm_kvp, (char*)xmlGetProp(node, BAD_CAST QSF_OBJECT_KVP), cm_value);
- kvp_frame_setter = (void(*)(QofEntity*, KvpFrame*))cm_setter;
- if(kvp_frame_setter != NULL) { kvp_frame_setter(qsf_ent, cm_kvp); }
- }
- if(safe_strcmp(qof_type, QOF_TYPE_COLLECT) == 0) {
- QofCollection *qsf_coll;
- QofIdType type;
- QofEntityReference *reference;
- QofParam *copy_param;
- /* retrieve the *type* of the collection, ignore any contents. */
- qsf_coll = cm_param->param_getfcn(qsf_ent, cm_param);
- type = qof_collection_get_type(qsf_coll);
- cm_guid = g_new(GUID, 1);
- if(TRUE != string_to_guid((char*)xmlNodeGetContent(node), cm_guid))
- {
- qof_backend_set_error(params->be, ERR_QSF_BAD_OBJ_GUID);
- PINFO (" string to guid collect failed for %s", xmlNodeGetContent(node));
- return;
- }
- // create a QofEntityReference with this type and GUID.
- // there is only one entity each time.
- // cm_guid contains the GUID of the reference.
- // type is the type of the reference.
- reference = g_new0(QofEntityReference, 1);
- reference->type = g_strdup(qsf_ent->e_type);
- reference->ref_guid = cm_guid;
- reference->ent_guid = &qsf_ent->guid;
- copy_param = g_new0(QofParam, 1);
- copy_param->param_name = g_strdup(cm_param->param_name);
- copy_param->param_type = g_strdup(cm_param->param_type);
- reference->param = copy_param;
- params->referenceList = g_list_append(params->referenceList, reference);
- }
- if(safe_strcmp(qof_type, QOF_TYPE_CHAR) == 0) {
- char_getter = (char (*)(xmlNodePtr))xmlNodeGetContent;
- cm_char = char_getter(node);
- char_setter = (void(*)(QofEntity*, char))cm_setter;
- if(char_setter != NULL) { char_setter(qsf_ent, cm_char); }
- }
-}
-
-QofBackend*
-qsf_backend_new(void)
-{
- QSFBackend *qsf_be;
- QofBackend *be;
-
- qsf_be = g_new0(QSFBackend, 1);
- be = (QofBackend*) qsf_be;
- qof_backend_init(be);
- qsf_be->params = g_new(qsf_param, 1);
- qsf_be->params->be = be;
- qsf_param_init(qsf_be->params);
- qsf_be->be.session_begin = qsf_session_begin;
-
- be->session_end = qsf_session_end;
- be->destroy_backend = qsf_destroy_backend;
- be->load = qsf_file_type;
- be->save_may_clobber_data = NULL;
- /* The QSF backend will always load and save the entire QSF XML file. */
- be->begin = NULL;
- be->commit = NULL;
- be->rollback = NULL;
- /* QSF uses the built-in SQL, not a dedicated SQL server. */
- be->compile_query = NULL;
- be->free_query = NULL;
- be->run_query = NULL;
- be->counter = NULL;
- /* The QSF backend is not multi-user. */
- be->events_pending = NULL;
- be->process_events = NULL;
-
- be->sync = qsf_write_file;
- /* use for maps, later. */
- be->load_config = qsf_load_config;
- be->get_config = qsf_get_config;
-
- qsf_be->fullpath = NULL;
- return be;
-}
-
-/** \brief The QOF method of loading each backend.
-
-QSF does not use a GnuCash module, it is loaded using the QOF
-method - QofBackendProvider.
-*/
-static void
-qsf_provider_free (QofBackendProvider *prov)
-{
- prov->provider_name = NULL;
- prov->access_method = NULL;
- g_free (prov);
-}
-
-/* although we call gettext here, none of the
-QofBackendProvider strings are translatable. */
-void
-qsf_provider_init(void)
-{
- QofBackendProvider *prov;
-
- #ifdef ENABLE_NLS
- setlocale (LC_ALL, "");
- bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR);
- bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
- textdomain (GETTEXT_PACKAGE);
- #endif
- prov = g_new0 (QofBackendProvider, 1);
- prov->provider_name = "QSF Backend Version 0.1";
- prov->access_method = "file";
- prov->partial_book_supported = TRUE;
- prov->backend_new = qsf_backend_new;
- prov->check_data_type = qsf_determine_file_type;
- prov->provider_free = qsf_provider_free;
- qof_backend_register_provider (prov);
-}
Deleted: gnucash/trunk/src/backend/qsf/qsf-dir.h.in
===================================================================
--- gnucash/trunk/src/backend/qsf/qsf-dir.h.in 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/backend/qsf/qsf-dir.h.in 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,26 +0,0 @@
-/***************************************************************************
- * qsf-xml.h.in
- *
- * Mon Dec 20 20:27:48 2004
- * Copyright 2004 Neil Williams
- * linux at codehelp.co.uk
- ****************************************************************************/
-
-/*
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#define QSF_SCHEMA_DIR "@-QSF_SCHEMA_DIR-@"
-
Deleted: gnucash/trunk/src/backend/qsf/qsf-map.xsd.xml
===================================================================
--- gnucash/trunk/src/backend/qsf/qsf-map.xsd.xml 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/backend/qsf/qsf-map.xsd.xml 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,116 +0,0 @@
-<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
-targetNamespace="http://qof.sourceforge.net/"
-xmlns:qsf-map="http://qof.sourceforge.net/">
-<xsd:annotation>
- <xsd:documentation xml:lang="en">
- Query Object Framework Serialization Format (QSF)
- Copyright 2004 Neil Williams linux at codehelp.co.uk
- QSF is part of QOF.
- QOF 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, write to the Free Software Foundation, Inc., 59
- Temple Place, Suite 330, Boston, MA 02111-1307 USA
- </xsd:documentation>
- </xsd:annotation>
-<xsd:element name="qsf-map" qsf-map:type="map-type"/>
-<xsd:complexType name="map-type">
- <xsd:sequence>
- <xsd:element name="definition" qsf-map:type="qsfdefinition"/>
- <xsd:element name="object" qsf-map:type="mapobject" minOccurs="1" maxOccurs="unbounded"/>
- </xsd:sequence>
-</xsd:complexType>
-<xsd:complexType name="qsfdefinition">
- <xsd:sequence>
- <xsd:element name="define" qsf-map:type="qsfdefine" minOccurs="2" maxOccurs="unbounded"/>
- <xsd:element name="default" qsf-map:type="qsfdefault" minOccurs="0" maxOccurs="unbounded"/>
- <xsd:element name="variable" qsf-map:type="qsfvariable" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- <xsd:attribute name="qof_version" type="xsd:positiveInteger"/>
-</xsd:complexType>
-<xsd:complexType name="qsfdefine">
- <xsd:simpleContent>
- <xsd:extension base="xsd:string">
- <xsd:attribute name="e_type" type="xsd:string"/>
- </xsd:extension>
- </xsd:simpleContent>
-</xsd:complexType>
-<xsd:complexType name="qsfdefault">
- <xsd:simpleContent>
- <xsd:extension base="xsd:string">
- <xsd:attribute name="name" type="xsd:string"/>
- <xsd:attribute name="type" type="xsd:string"/>
- <xsd:attribute name="value" type="xsd:string"/>
- </xsd:extension>
- </xsd:simpleContent>
-</xsd:complexType>
-<xsd:complexType name="qsfvariable">
- <xsd:simpleContent>
- <xsd:extension base="xsd:string">
- <xsd:attribute name="name" type="xsd:string"/>
- <xsd:attribute name="type" type="xsd:string"/>
- <xsd:attribute name="value" type="xsd:string"/>
- </xsd:extension>
- </xsd:simpleContent>
-</xsd:complexType>
-<xsd:complexType name="mapobject">
- <xsd:sequence>
- <xsd:element name="calculate" qsf-map:type="qsfcalculate" minOccurs="1" maxOccurs="unbounded"/>
- </xsd:sequence>
- <xsd:attribute name="type" type="xsd:string"/>
- <xsd:attribute name="value" type="xsd:string"/>
-</xsd:complexType>
-<xsd:complexType name="qsfcalculate">
- <xsd:sequence>
- <xsd:element name="set" qsf-map:type="qsf_set" minOccurs="0" maxOccurs="1"/>
- <xsd:element name="if" qsf-map:type="qsf_if" minOccurs="0" maxOccurs="unbounded"/>
- <xsd:element name="equals" qsf-map:type="qsf_equal" minOccurs="0" maxOccurs="unbounded"/>
- <xsd:element name="else" qsf-map:type="qsf_else" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- <xsd:attribute name="type" type="xsd:string"/>
- <xsd:attribute name="value" type="xsd:string"/>
-</xsd:complexType>
-<xsd:complexType name="qsf_set">
- <xsd:simpleContent>
- <xsd:extension base="xsd:string">
- <xsd:attribute name="option" type="xsd:string" use="optional"/>
- <xsd:attribute name="format" type="xsd:string" use="optional"/>
- <xsd:attribute name="object" type="xsd:string" use="optional"/>
- </xsd:extension>
- </xsd:simpleContent>
-</xsd:complexType>
-<xsd:complexType name="qsf_if">
- <xsd:sequence>
- <xsd:element name="set" qsf-map:type="qsf_set" minOccurs="0" maxOccurs="1"/>
- <xsd:element name="equals" qsf-map:type="qsf_equal" minOccurs="0" maxOccurs="1"/>
- </xsd:sequence>
- <xsd:attribute name="boolean" type="xsd:string" use="optional"/>
- <xsd:attribute name="type" type="xsd:string" use="optional"/>
- <xsd:attribute name="value" type="xsd:string" use="optional"/>
- <xsd:attribute name="string" type="xsd:string" use="optional"/>
-</xsd:complexType>
-<xsd:complexType name="qsf_else">
- <xsd:sequence>
- <xsd:element name="set" qsf-map:type="qsf_set" minOccurs="0" maxOccurs="1"/>
- <xsd:element name="equals" qsf-map:type="qsf_equal" minOccurs="0" maxOccurs="1"/>
- </xsd:sequence>
- <xsd:attribute name="type" type="xsd:string"/>
- <xsd:attribute name="value" type="xsd:string"/>
-</xsd:complexType>
-<xsd:complexType name="qsf_equal">
- <xsd:sequence>
- <xsd:element name="set" qsf-map:type="qsf_set" minOccurs="0" maxOccurs="1"/>
- <xsd:element name="equals" qsf-map:type="qsf_equal" minOccurs="0" maxOccurs="1"/>
- </xsd:sequence>
- <xsd:attribute name="type" type="xsd:string"/>
- <xsd:attribute name="value" type="xsd:string"/>
-</xsd:complexType>
-
-</xsd:schema>
-
Deleted: gnucash/trunk/src/backend/qsf/qsf-object.xsd.xml
===================================================================
--- gnucash/trunk/src/backend/qsf/qsf-object.xsd.xml 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/backend/qsf/qsf-object.xsd.xml 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,154 +0,0 @@
-<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
-targetNamespace="http://qof.sourceforge.net/"
-xmlns:qof-qsf="http://qof.sourceforge.net/"
-elementFormDefault="qualified"
-attributeFormDefault="unqualified" xml:lang="en-GB">
- <xsd:annotation>
- <xsd:documentation xml:lang="en">
- Query Object Framework Serialization Format (QSF)
- Copyright 2004-5 Neil Williams linux at codehelp.co.uk
- QSF is part of QOF.
- QOF 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, write to the Free Software Foundation, Inc., 59
- Temple Place, Suite 330, Boston, MA 02111-1307 USA
- </xsd:documentation>
- </xsd:annotation>
-<xsd:element name="qof-qsf" type="qof-qsf:qsftype"/>
-<xsd:complexType name="qsftype">
- <xsd:sequence>
- <xsd:element name="book" type="qof-qsf:qofbook" minOccurs="1" maxOccurs="unbounded"/>
- </xsd:sequence>
-</xsd:complexType>
-<xsd:complexType name="qofbook">
- <xsd:sequence>
- <xsd:element name="book-guid" type="xsd:string" minOccurs="1" maxOccurs="1"/>
- <xsd:element name="object" type="qof-qsf:qsfobject" minOccurs="0" maxOccurs="unbounded"/>
- </xsd:sequence>
- <xsd:attribute name="count" type="xsd:positiveInteger" use="optional"/>
-</xsd:complexType>
-<xsd:complexType name="qsfobject">
- <xsd:sequence>
- <xsd:element name="string" minOccurs="0" maxOccurs="unbounded">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:string">
- <xsd:attribute name="type" type="xsd:string" use="required"/>
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="guid" minOccurs="0" maxOccurs="unbounded">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:hexBinary">
- <xsd:attribute name="type" type="xsd:string" use="required"/>
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="boolean" minOccurs="0" maxOccurs="unbounded">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:boolean">
- <xsd:attribute name="type" type="xsd:string" use="required"/>
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="numeric" minOccurs="0" maxOccurs="unbounded">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:string">
- <xsd:attribute name="type" type="xsd:string" use="required"/>
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="date" minOccurs="0" maxOccurs="unbounded" >
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:dateTime">
- <xsd:attribute name="type" type="xsd:string" use="required"/>
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="gint32" minOccurs="0" maxOccurs="unbounded">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:int">
- <xsd:attribute name="type" type="xsd:string" use="required"/>
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="gint64" minOccurs="0" maxOccurs="unbounded">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:long">
- <xsd:attribute name="type" type="xsd:string" use="required"/>
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="double" minOccurs="0" maxOccurs="unbounded">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:double">
- <xsd:attribute name="type" type="xsd:string" use="required"/>
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="character" minOccurs="0" maxOccurs="unbounded">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:string">
- <xsd:attribute name="type" type="xsd:string" use="required"/>
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="kvp" minOccurs="0" maxOccurs="unbounded">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:string">
- <xsd:attribute name="type" type="xsd:string" use="required"/>
- <xsd:attribute name="path" type="xsd:string" use="required"/>
- <xsd:attribute name="value" type="xsd:string" use="required"/>
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="collection" minOccurs="0" maxOccurs="unbounded">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:hexBinary">
- <xsd:attribute name="type" type="xsd:string" use="required"/>
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
- <xsd:element name="choice" minOccurs="0" maxOccurs="unbounded">
- <xsd:complexType>
- <xsd:simpleContent>
- <xsd:extension base="xsd:hexBinary">
- <xsd:attribute name="type" type="xsd:string" use="required"/>
- <xsd:attribute name="name" type="xsd:string" use="required"/>
- </xsd:extension>
- </xsd:simpleContent>
- </xsd:complexType>
- </xsd:element>
-</xsd:sequence>
- <xsd:attribute name="type" type="xsd:string" use="required"/>
- <xsd:attribute name="count" type="xsd:positiveInteger" use="optional"/>
-</xsd:complexType>
-</xsd:schema>
Deleted: gnucash/trunk/src/backend/qsf/qsf-xml-map.c
===================================================================
--- gnucash/trunk/src/backend/qsf/qsf-xml-map.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/backend/qsf/qsf-xml-map.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,711 +0,0 @@
-/***************************************************************************
- * qsf-xml-map.c
- *
- * Sat Jan 1 07:31:55 2005
- * Copyright 2005 Neil Williams
- * linux at codehelp.co.uk
- ****************************************************************************/
-
-/*
- * 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 Library General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#define _GNU_SOURCE
-
-#include <libxml/xmlversion.h>
-#include <libxml/xmlmemory.h>
-#include <libxml/tree.h>
-#include <libxml/parser.h>
-#include <libxml/xmlschemas.h>
-#include "qof-backend-qsf.h"
-#include "qsf-xml.h"
-#include "qsf-dir.h"
-
-static void
-qsf_date_default_handler(const char *default_name, GHashTable *qsf_default_hash,
- xmlNodePtr parent_tag, xmlNodePtr import_node, xmlNsPtr ns)
-{
- xmlNodePtr output_parent;
- time_t *qsf_time;
- char date_as_string[QSF_DATE_LENGTH];
-
- output_parent = xmlAddChild(parent_tag, xmlNewNode(ns,
- xmlGetProp(import_node, BAD_CAST QSF_OBJECT_TYPE)));
- xmlNewProp(output_parent, BAD_CAST QSF_OBJECT_TYPE,
- xmlGetProp(import_node, BAD_CAST MAP_VALUE_ATTR));
- qsf_time = (time_t*)g_hash_table_lookup(qsf_default_hash, default_name);
- strftime(date_as_string, QSF_DATE_LENGTH, QSF_XSD_TIME, gmtime(qsf_time));
- xmlNodeAddContent(output_parent, BAD_CAST date_as_string);
-}
-
-static void
-qsf_string_default_handler(const char *default_name, GHashTable *qsf_default_hash,
- xmlNodePtr parent_tag, xmlNodePtr import_node, xmlNsPtr ns)
-{
- xmlNodePtr node;
- xmlChar *output;
-
- node = xmlAddChild(parent_tag,
- xmlNewNode(ns, xmlGetProp(import_node, BAD_CAST QSF_OBJECT_TYPE)));
- xmlNewProp(node, BAD_CAST QSF_OBJECT_TYPE,
- xmlGetProp(import_node, BAD_CAST MAP_VALUE_ATTR));
- output = (xmlChar *)g_hash_table_lookup(qsf_default_hash, default_name);
- xmlNodeAddContent(node, output);
-}
-
-void
-qsf_map_validation_handler(xmlNodePtr child, xmlNsPtr ns, qsf_validator *valid)
-{
- xmlChar *qof_version, *match;
- GString *buff;
- xmlNodePtr child_node;
-
- if (qsf_is_element(child, ns, MAP_DEFINITION_TAG)) {
- qof_version = xmlGetProp(child, BAD_CAST MAP_QOF_VERSION);
- buff = g_string_new(" ");
- g_string_printf(buff, "%i", QSF_QOF_VERSION);
- if(xmlStrcmp(qof_version, BAD_CAST buff->str) != 0)
- {
- valid->error_state = ERR_QSF_BAD_QOF_VERSION;
- return;
- }
- for(child_node = child->children; child_node != NULL;
- child_node = child_node->next)
- {
- if (qsf_is_element(child_node, ns, MAP_DEFINE_TAG)) {
- g_hash_table_insert(valid->validation_table,
- xmlGetProp(child_node, BAD_CAST MAP_E_TYPE),
- xmlNodeGetContent(child_node));
- }
- }
- }
- if(qsf_is_element(child, ns, MAP_OBJECT_TAG)) {
- match = NULL;
- match = BAD_CAST g_hash_table_lookup( valid->validation_table,
- xmlGetProp(child, BAD_CAST MAP_TYPE_ATTR));
- if(match) {
- valid->map_calculated_count++;
- }
- }
-}
-
-gboolean is_qsf_object_with_map_be(char *map_file, qsf_param *params)
-{
- xmlDocPtr doc, map_doc;
- int valid_count;
- struct qsf_node_iterate iter;
- xmlNodePtr map_root, object_root;
- xmlNsPtr map_ns;
- qsf_validator valid;
- char *path;
- gchar *map_path;
-
- g_return_val_if_fail((params != NULL),FALSE);
- path = g_strdup(params->filepath);
- map_path = g_strdup_printf("%s/%s", QSF_SCHEMA_DIR, map_file);
- if(path == NULL) {
- qof_backend_set_error(params->be, ERR_FILEIO_FILE_NOT_FOUND);
- return FALSE;
- }
- doc = xmlParseFile(path);
- if(doc == NULL) {
- qof_backend_set_error(params->be, ERR_FILEIO_PARSE_ERROR);
- return FALSE;
- }
- if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc)) {
- qof_backend_set_error(params->be, ERR_QSF_INVALID_OBJ);
- return FALSE;
- }
- object_root = xmlDocGetRootElement(doc);
- if(map_path == NULL) {
- qof_backend_set_error(params->be, ERR_FILEIO_FILE_NOT_FOUND);
- return FALSE;
- }
- valid.validation_table = g_hash_table_new(g_str_hash, g_str_equal);
- map_doc = xmlParseFile(map_path);
- if(map_doc == NULL) {
- qof_backend_set_error(params->be, ERR_FILEIO_PARSE_ERROR);
- return FALSE;
- }
- if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_MAP_SCHEMA, map_doc)) {
- qof_backend_set_error(params->be, ERR_QSF_INVALID_MAP);
- return FALSE;
- }
- map_root = xmlDocGetRootElement(map_doc);
- valid.map_calculated_count = 0;
- valid.valid_object_count = 0;
- valid.qof_registered_count = 0;
- valid.error_state = ERR_BACKEND_NO_ERR;
- map_ns = map_root->ns;
- iter.ns = object_root->ns;
- qsf_valid_foreach(object_root, qsf_object_validation_handler, &iter, &valid);
- iter.ns = map_ns;
- qsf_valid_foreach(map_root, qsf_map_validation_handler, &iter, &valid);
- if (valid.error_state != ERR_BACKEND_NO_ERR) {
- qof_backend_set_error(params->be, valid.error_state);
- g_hash_table_destroy(valid.validation_table);
- return FALSE;
- }
- valid_count = 0 - g_hash_table_size(valid.validation_table);
- valid_count += valid.map_calculated_count;
- valid_count += valid.valid_object_count;
- g_hash_table_destroy(valid.validation_table);
- if(valid_count == 0) {
- qof_backend_get_error(params->be);
- return TRUE;
- }
- qof_backend_set_error(params->be, ERR_QSF_WRONG_MAP);
- /* the object is OK, only the map is wrong. */
- return TRUE;
-}
-
-gboolean is_qsf_object_with_map(const char *path, char *map_file)
-{
- xmlDocPtr doc, map_doc;
- int valid_count;
- struct qsf_node_iterate iter;
- xmlNodePtr map_root, object_root;
- xmlNsPtr map_ns;
- qsf_validator valid;
- gchar *map_path;
-
- map_path = g_strdup_printf("%s/%s", QSF_SCHEMA_DIR, map_file);
- if(path == NULL) {
- return FALSE;
- }
- doc = xmlParseFile(path);
- if(doc == NULL) {
- return FALSE;
- }
- if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc)) {
- return FALSE;
- }
- object_root = xmlDocGetRootElement(doc);
- if(map_path == NULL) {
- return FALSE;
- }
- valid.validation_table = g_hash_table_new(g_str_hash, g_str_equal);
- map_doc = xmlParseFile(map_path);
- if(map_doc == NULL) {
- return FALSE;
- }
- if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_MAP_SCHEMA, map_doc)) {
- return FALSE;
- }
- map_root = xmlDocGetRootElement(map_doc);
- valid.map_calculated_count = 0;
- valid.valid_object_count = 0;
- valid.error_state = ERR_BACKEND_NO_ERR;
- map_ns = map_root->ns;
- iter.ns = map_ns;
- qsf_valid_foreach(map_root, qsf_map_validation_handler, &iter, &valid);
- iter.ns = object_root->ns;
- qsf_valid_foreach(object_root, qsf_object_validation_handler, &iter, &valid);
- if (valid.error_state != ERR_BACKEND_NO_ERR) {
- g_hash_table_destroy(valid.validation_table);
- return FALSE;
- }
- valid_count = 0 - g_hash_table_size(valid.validation_table);
- valid_count += valid.map_calculated_count;
- valid_count += valid.valid_object_count;
- g_hash_table_destroy(valid.validation_table);
- if(valid_count == 0) {
- return TRUE;
- }
- return FALSE;
-}
-
-gboolean is_qsf_map_be(qsf_param *params)
-{
- xmlDocPtr doc;
- struct qsf_node_iterate iter;
- qsf_validator valid;
- xmlNodePtr map_root;
- xmlNsPtr map_ns;
- char *path;
-
- g_return_val_if_fail((params != NULL),FALSE);
- qof_backend_get_error(params->be);
- path = g_strdup(params->filepath);
- if(path == NULL) {
- qof_backend_set_error(params->be, ERR_FILEIO_FILE_NOT_FOUND);
- return FALSE;
- }
- doc = xmlParseFile(path);
- if(doc == NULL) {
- qof_backend_set_error(params->be, ERR_FILEIO_PARSE_ERROR);
- return FALSE;
- }
- if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_MAP_SCHEMA, doc)) {
- qof_backend_set_error(params->be, ERR_QSF_INVALID_MAP);
- return FALSE;
- }
- map_root = xmlDocGetRootElement(doc);
- map_ns = map_root->ns;
- iter.ns = map_ns;
- valid.error_state = ERR_BACKEND_NO_ERR;
- qsf_valid_foreach(map_root, qsf_map_validation_handler, &iter, &valid);
- if (valid.error_state != ERR_BACKEND_NO_ERR) {
- qof_backend_set_error(params->be, valid.error_state);
- g_hash_table_destroy(valid.validation_table);
- return FALSE;
- }
- qof_backend_get_error(params->be);
- g_hash_table_destroy(valid.validation_table);
- return TRUE;
-}
-
-gboolean is_qsf_map(const char *path)
-{
- xmlDocPtr doc;
- struct qsf_node_iterate iter;
- qsf_validator valid;
- xmlNodePtr map_root;
- xmlNsPtr map_ns;
-
- g_return_val_if_fail((path != NULL),FALSE);
- if(path == NULL) { return FALSE; }
- doc = xmlParseFile(path);
- if(doc == NULL) { return FALSE; }
- if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_MAP_SCHEMA, doc)) {
- return FALSE;
- }
- map_root = xmlDocGetRootElement(doc);
- map_ns = map_root->ns;
- iter.ns = map_ns;
- valid.error_state = ERR_BACKEND_NO_ERR;
- qsf_valid_foreach(map_root, qsf_map_validation_handler, &iter, &valid);
- if (valid.error_state != ERR_BACKEND_NO_ERR) {
- g_hash_table_destroy(valid.validation_table);
- return FALSE;
- }
- g_hash_table_destroy(valid.validation_table);
- return TRUE;
-}
-
-
-static void
-qsf_map_default_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params )
-{
- xmlChar *qsf_enum;
-
- g_return_if_fail(params->qsf_define_hash != NULL);
- if (qsf_is_element(child, ns, MAP_DEFINE_TAG)) {
- if(NULL == g_hash_table_lookup(params->qsf_define_hash,
- xmlGetProp(child, BAD_CAST MAP_E_TYPE)))
- {
- g_hash_table_insert(params->qsf_define_hash,
- xmlGetProp(child, BAD_CAST MAP_E_TYPE), params->child_node);
- }
- else {
- qof_backend_set_error(params->be, ERR_QSF_BAD_MAP);
- return;
- }
- }
- if(qsf_is_element(child, ns, MAP_DEFAULT_TAG)) {
- if(qsf_strings_equal(xmlGetProp(child, BAD_CAST MAP_TYPE_ATTR), MAP_ENUM_TYPE))
- {
- qsf_enum = xmlNodeGetContent(child);
- /** Use content to discriminate enums in QOF */
- /** \todo FIXME: the default enum value is not used
- implemented properly or fully handled.
- */
- if(NULL == g_hash_table_lookup(params->qsf_default_hash,
- xmlNodeGetContent(child)))
- {
- g_hash_table_insert(params->qsf_default_hash,
- xmlNodeGetContent(child), child);
- }
- else
- {
- qof_backend_set_error(params->be, ERR_QSF_BAD_MAP);
- return;
- }
- }
- /** Non-enum defaults */
- else {
- if(NULL == g_hash_table_lookup(params->qsf_default_hash,
- xmlGetProp(child, BAD_CAST MAP_NAME_ATTR)))
- {
- g_hash_table_insert(params->qsf_default_hash,
- xmlGetProp(child, BAD_CAST MAP_NAME_ATTR), child);
- }
- else
-/* if(0 != xmlHashAddEntry(params->default_map,
- xmlGetProp(child_node, MAP_NAME_ATTR), child_node))*/
- {
- qof_backend_set_error(params->be, ERR_QSF_BAD_MAP);
- return;
- }
- }
- }
-}
-
-void
-qsf_map_top_node_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params)
-{
- xmlChar *qof_version;
- GString *buff;
- struct qsf_node_iterate iter;
-
- if(!params->qsf_define_hash) return;
- if(!params->qsf_default_hash) return;
- if(qsf_is_element(child, ns, MAP_DEFINITION_TAG)) {
- qof_version = xmlGetProp(child, BAD_CAST MAP_QOF_VERSION);
- buff = g_string_new(" ");
- g_string_printf(buff, "%i", QSF_QOF_VERSION);
- if(xmlStrcmp(qof_version, BAD_CAST buff->str) != 0) {
- qof_backend_set_error(params->be, ERR_QSF_BAD_QOF_VERSION);
- return;
- }
- iter.ns = ns;
- qsf_node_foreach(child, qsf_map_default_handler, &iter, params);
- }
-}
-
-static char*
-qsf_else_set_value(xmlNodePtr parent, GHashTable *default_hash,
- char *content, xmlNsPtr map_ns)
-{
- xmlNodePtr cur_node;
-
- content = NULL;
- for(cur_node = parent->children; cur_node != NULL; cur_node = cur_node->next)
- {
- if(qsf_is_element(cur_node, map_ns, QSF_CONDITIONAL_SET)) {
- content = (char*)xmlNodeGetContent(cur_node);
- return content;
- }
- }
- return NULL;
-}
-
-/* Handles the set tag in the map.
-This function will be overhauled once inside QOF
-QOF hook required for "Lookup in the receiving application"
-*/
-static char*
-qsf_set_handler(xmlNodePtr parent, GHashTable *default_hash,
- char *content, qsf_param *params)
-{
- xmlNodePtr cur_node, lookup_node;
-
- content = NULL;
- for(cur_node = parent->children; cur_node != NULL; cur_node = cur_node->next)
- {
- if(qsf_is_element(cur_node, params->map_ns, QSF_CONDITIONAL_SET))
- {
- content = (char*)xmlGetProp(cur_node, BAD_CAST QSF_OPTION);
- if(qsf_strings_equal(xmlGetProp(cur_node, BAD_CAST QSF_OPTION), "qsf_lookup_string"))
- {
- lookup_node = (xmlNodePtr) g_hash_table_lookup(default_hash,
- xmlNodeGetContent(cur_node));
- content = (char*)xmlGetProp(lookup_node, BAD_CAST MAP_VALUE_ATTR);
- /** \todo FIXME: do the lookup. type is defined by output object. */
- /* Find by name, get GUID, return GUID as string. */
- g_message("Lookup %s in the receiving application\n", content );
- return content;
- }
- if(content)
- {
- lookup_node = (xmlNodePtr) g_hash_table_lookup(default_hash,
- xmlNodeGetContent(cur_node));
- content = (char*)xmlGetProp(lookup_node, BAD_CAST "value");
- return content;
- }
- content = (char*)xmlGetProp(parent, BAD_CAST "boolean");
- if(!content) {
- /** \todo Check qsf_parameter_hash arguments */
- lookup_node = (xmlNodePtr) g_hash_table_lookup(params->qsf_parameter_hash,
- xmlGetProp(parent->parent, BAD_CAST MAP_TYPE_ATTR));
- if(lookup_node) { return (char*)xmlNodeGetContent(lookup_node); }
- return (char*)xmlNodeGetContent(cur_node);
- }
- }
- }
- return NULL;
-}
-
-static void
-qsf_calculate_else(xmlNodePtr param_node, xmlNodePtr child, qsf_param *params)
-{
- xmlNodePtr export_node;
- xmlChar *output_content, *object_data;
-
- if(qsf_is_element(param_node, params->map_ns, QSF_CONDITIONAL_ELSE)) {
- if(params->boolean_calculation_done == 0) {
- output_content = object_data = NULL;
- output_content = BAD_CAST qsf_set_handler(param_node,
- params->qsf_default_hash, (char*)output_content, params);
- if(output_content == NULL) {
- output_content = xmlGetProp(param_node, BAD_CAST MAP_TYPE_ATTR);
- object_data = BAD_CAST qsf_else_set_value(param_node, params->qsf_default_hash,
- (char*)output_content, params->map_ns);
- output_content = BAD_CAST xmlGetProp( (xmlNodePtr) g_hash_table_lookup(
- params->qsf_default_hash, object_data), BAD_CAST MAP_VALUE_ATTR);
- }
- if(object_data != NULL) {
- export_node =(xmlNodePtr) g_hash_table_lookup(
- params->qsf_parameter_hash,
- xmlGetProp(params->child_node, BAD_CAST QSF_OBJECT_TYPE));
- object_data = xmlNodeGetContent(export_node);
- }
- if(output_content != NULL) { object_data = output_content; }
- export_node = xmlAddChild(params->lister, xmlNewNode(params->qsf_ns,
- xmlGetProp(child, BAD_CAST QSF_OBJECT_TYPE)));
- xmlNewProp(export_node, BAD_CAST QSF_OBJECT_TYPE,
- xmlGetProp(child, BAD_CAST MAP_VALUE_ATTR));
- xmlNodeAddContent(export_node, object_data);
- params->boolean_calculation_done = 1;
- }
- }
-}
-
-static void
-qsf_set_format_value(xmlChar *format, char *qsf_time_now_as_string,
- xmlNodePtr cur_node, qsf_param *params)
-{
- int result;
- xmlChar *content;
- time_t *output;
- struct tm *tmp;
- time_t tester;
- xmlNodePtr kl;
- regex_t reg;
-
- /** Comments retained - this behaves a little strangely */
-
- result = 0;
- if(format == NULL) { return; }
- content = xmlNodeGetContent(cur_node);
- output = (time_t*) g_hash_table_lookup(params->qsf_default_hash, content);
- if(!output) {
- /** No default time set, use the object time */
- /** fill the time structs with temp data */
- tester = time(NULL);
- tmp = gmtime(&tester);
- /** Lookup the object value to read */
- /** \todo qsf_parameter_hash check correct arguments */
- kl = (xmlNodePtr) g_hash_table_lookup(params->qsf_parameter_hash, content);
- if(!kl) {
- printf("no suitable date set.\n");
- return;
- }
- /** Read the object value as a dateTime */
- strptime((char*)xmlNodeGetContent(kl), QSF_XSD_TIME, tmp);
- if(!tmp) {
- printf("empty date field in QSF object.\n");
- return;
- }
- tester = mktime(tmp);
- output = &tester;
- }
- result = regcomp(®, "%[a-zA-Z]", REG_EXTENDED|REG_NOSUB);
- result = regexec(®, (char*)format,(size_t)0,NULL,0);
- if(result == REG_NOMATCH) { format = BAD_CAST "%F"; }
- regfree(®);
- /** QSF_DATE_LENGTH preset for all internal and QSF_XSD_TIME string formats.
- */
- strftime(qsf_time_now_as_string, QSF_DATE_LENGTH, (char*)format, gmtime(output));
-}
-
-static void
-qsf_boolean_set_value(xmlNodePtr parent, qsf_param *params,
- char *content, xmlNsPtr map_ns)
-{
- xmlNodePtr cur_node;
- xmlChar *boolean_name;
-
- boolean_name = NULL;
- for(cur_node = parent->children; cur_node != NULL; cur_node = cur_node->next) {
- if(qsf_is_element(cur_node, map_ns, QSF_CONDITIONAL_SET)) {
- boolean_name = xmlGetProp(cur_node, BAD_CAST QSF_FORMATTING_OPTION);
- qsf_set_format_value(boolean_name, content, cur_node, params);
- }
- }
-}
-
-static void
-qsf_calculate_conditional(xmlNodePtr param_node, xmlNodePtr child, qsf_param *params)
-{
- xmlNodePtr export_node;
- xmlChar *output_content;
-
- output_content = NULL;
- if(qsf_is_element(param_node, params->map_ns, QSF_CONDITIONAL)) {
- printf("param_node=%s\n", param_node->name);
- if(params->boolean_calculation_done == 0) {
- /* set handler */
- output_content = BAD_CAST qsf_set_handler(param_node, params->qsf_default_hash,
- (char*)output_content, params);
- /* If the 'if' contains a boolean that has a default value */
- if(output_content == NULL) {
- if(NULL != xmlGetProp(param_node, BAD_CAST QSF_BOOLEAN_DEFAULT)) {
- output_content = xmlGetProp( (xmlNodePtr) g_hash_table_lookup(
- params->qsf_default_hash, xmlGetProp(param_node,
- BAD_CAST QSF_BOOLEAN_DEFAULT) ), BAD_CAST MAP_VALUE_ATTR);
- }
- /* Is the default set to true? */
- if( 0 == qsf_compare_tag_strings(output_content, QSF_XML_BOOLEAN_TEST))
- {
- qsf_boolean_set_value(param_node, params, (char*)output_content, params->map_ns);
- export_node = xmlAddChild(params->lister, xmlNewNode(params->qsf_ns,
- xmlGetProp(child, BAD_CAST QSF_OBJECT_TYPE)));
- xmlNewProp(export_node, BAD_CAST QSF_OBJECT_TYPE,
- xmlGetProp(child, BAD_CAST MAP_VALUE_ATTR));
- xmlNodeAddContent(export_node, output_content);
- params->boolean_calculation_done = 1;
- }
- }
- }
- }
-}
-
-static xmlNodePtr
-qsf_add_object_tag(qsf_param *params, int count)
-{
- xmlNodePtr extra_node;
- GString *str;
- xmlChar *property;
-
- str = g_string_new (" ");
- g_string_printf(str, "%i", count);
- extra_node = NULL;
- extra_node = xmlAddChild(params->output_node,
- xmlNewNode(params->qsf_ns, BAD_CAST QSF_OBJECT_TAG));
- xmlNewProp(extra_node, BAD_CAST QSF_OBJECT_TYPE,
- xmlGetProp(params->cur_node, BAD_CAST QSF_OBJECT_TYPE));
- property = xmlCharStrdup(str->str);
- xmlNewProp(extra_node, BAD_CAST QSF_OBJECT_COUNT, property);
- return extra_node;
-}
-
-void
-qsf_map_object_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params)
-{
- xmlNodePtr param_node, export_node;
- xmlNsPtr map_ns, qsf_ns;
- xmlChar *output_content;
- int result, count;
-
- map_ns = ns;
- qsf_ns = params->qsf_ns;
- param_node = NULL;
- result = 0;
- count = params->count;
- if(child == NULL) { return; }
- if(ns == NULL) { return; }
- params->boolean_calculation_done = 0;
-
- if(qsf_is_element(child, map_ns, MAP_CALCULATE_TAG)) {
- params->boolean_calculation_done = 0;
- for(param_node = child->children; param_node != NULL;
- param_node = param_node->next)
- {
- output_content = NULL;
- export_node = NULL;
- if(!params->lister) { params->lister = qsf_add_object_tag(params, count); }
- if(qsf_is_element(param_node, map_ns, "set"))
- {
- /* Map the pre-defined defaults */
- if(0 == qsf_compare_tag_strings(
- xmlNodeGetContent(param_node), "qsf_enquiry_date"))
- {
- qsf_string_default_handler("qsf_enquiry_date",
- params->qsf_default_hash, params->lister, child, qsf_ns);
- }
- if(0 == qsf_compare_tag_strings(
- xmlNodeGetContent(param_node), "qsf_time_now"))
- {
- qsf_date_default_handler("qsf_time_now",
- params->qsf_default_hash, params->lister, child, qsf_ns);
- }
- if(0 == qsf_compare_tag_strings(
- xmlNodeGetContent(param_node), "qsf_time_string"))
- {
- qsf_string_default_handler("qsf_time_string",
- params->qsf_default_hash, params->lister, child, qsf_ns);
- }
- output_content = xmlNodeGetContent(param_node);
- if(output_content != NULL) {
- output_content = xmlNodeGetContent((xmlNodePtr) g_hash_table_lookup(
- params->qsf_parameter_hash, xmlGetProp(child, BAD_CAST MAP_TYPE_ATTR)));
- if(output_content != NULL) {
- export_node = xmlAddChild(params->lister, xmlNewNode(qsf_ns,
- xmlGetProp(child, BAD_CAST QSF_OBJECT_TYPE)));
- xmlNewProp(export_node, BAD_CAST QSF_OBJECT_TYPE,
- xmlGetProp(child, BAD_CAST MAP_VALUE_ATTR));
- xmlNodeAddContent(export_node, output_content);
- xmlFree(output_content);
- }
- }
- }
-
- qsf_calculate_conditional( param_node, child, params);
- qsf_calculate_else(param_node, child, params);
- }
-
- /* calculate_map currently not in use */
- /* ensure uniqueness of the key before re-instating */
-/* result = xmlHashAddEntry2(calculate_map,
- xmlGetProp(child_node, MAP_TYPE_ATTR),
- xmlGetProp(child_node, MAP_VALUE_ATTR), child_node);
- if(result != 0) {
- printf("add entry to calculate hash failed. %s\t%s\t%s.\n",
- xmlGetProp(child_node, MAP_TYPE_ATTR),
- xmlGetProp(child_node, MAP_VALUE_ATTR), child_node->name);
- return;
- }
-
- is_qsf_object_with_map(path, map_path);
-*/
- }
-}
-xmlDocPtr
-qsf_object_convert(xmlDocPtr mapDoc, xmlNodePtr qsf_root, qsf_param *params)
-{
- struct qsf_node_iterate iter;
- xmlDocPtr output_doc;
- xmlNode *cur_node;
- xmlNode *map_root, *output_root, *output_node;
-
- output_doc = xmlNewDoc(BAD_CAST QSF_XML_VERSION);
- output_root = xmlDocCopyNode(qsf_root,output_doc,2);
- xmlSetNs(output_root, params->qsf_ns);
- output_node = NULL;
-
- qsf_node_foreach(qsf_root, qsf_object_node_handler, &iter, params);
- map_root = xmlDocGetRootElement(mapDoc);
-
- iter.ns = params->map_ns;
- qsf_node_foreach(map_root, qsf_map_top_node_handler, &iter, params);
-
-// iter.ns = qsf_ns;
-// qsf_node_foreach(qsf_root, qsf_map_object_handler, &iter, params);
- for(cur_node = map_root->children; cur_node != NULL; cur_node = cur_node->next)
- {
- params->cur_node = cur_node;
- params->count = 0;
- if(qsf_is_element(cur_node, params->map_ns, MAP_OBJECT_TAG))
- {
- params->lister = NULL;
- params->count++;
- iter.ns = params->map_ns;
- qsf_node_foreach(cur_node, qsf_map_object_handler, &iter, params);
- }
- }
- params->file_type = OUR_QSF_OBJ;
- return output_doc;
-}
Deleted: gnucash/trunk/src/backend/qsf/qsf-xml.c
===================================================================
--- gnucash/trunk/src/backend/qsf/qsf-xml.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/backend/qsf/qsf-xml.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,349 +0,0 @@
-/***************************************************************************
- * qsf-xml.c
- *
- * Fri Nov 26 19:29:47 2004
- * Copyright 2004-2005 Neil Williams <linux at codehelp.co.uk>
- *
- ****************************************************************************/
-/*
- * 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 Library General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#define _GNU_SOURCE
-
-#include <libxml/xmlversion.h>
-#include "qof-backend-qsf.h"
-#include "qsf-dir.h"
-#include "qsf-xml.h"
-
-static QofLogModule log_module = QOF_MOD_QSF;
-
-void qsf_free_params(qsf_param *params)
-{
- g_hash_table_destroy(params->qsf_calculate_hash);
- g_hash_table_destroy(params->qsf_default_hash);
- if(params->referenceList) {
- g_list_free(params->referenceList);
- }
- g_slist_free(params->supported_types);
- if(params->map_ns) { xmlFreeNs(params->map_ns); }
-}
-
-int
-qsf_compare_tag_strings(const xmlChar *node_name, char *tag_name)
-{
- return xmlStrcmp(node_name, (const xmlChar *)tag_name);
-}
-
-int
-qsf_strings_equal(const xmlChar *node_name, char *tag_name)
-{
- if(0 == qsf_compare_tag_strings(node_name, tag_name)) { return 1; }
- return 0;
-}
-
-int
-qsf_is_element(xmlNodePtr a, xmlNsPtr ns, char *c)
-{
- g_return_val_if_fail(a != NULL, 0);
- g_return_val_if_fail(ns != NULL, 0);
- g_return_val_if_fail(c != NULL, 0);
- if ((a->ns == ns) && (a->type == XML_ELEMENT_NODE) &&
- qsf_strings_equal(a->name, c)) { return 1; }
- return 0;
-}
-
-int
-qsf_check_tag(qsf_param *params, char *qof_type)
-{
- return qsf_is_element(params->child_node, params->qsf_ns, qof_type);
-}
-
-gboolean
-qsf_is_valid(const char *schema_dir, const char* schema_filename, xmlDocPtr doc)
-{
- xmlSchemaParserCtxtPtr qsf_schema_file;
- xmlSchemaPtr qsf_schema;
- xmlSchemaValidCtxtPtr qsf_context;
- gchar *schema_path;
- gint result;
-
- g_return_val_if_fail(doc || schema_filename, FALSE);
- schema_path = g_strdup_printf("%s/%s", schema_dir, schema_filename);
- qsf_schema_file = xmlSchemaNewParserCtxt(schema_path);
- qsf_schema = xmlSchemaParse(qsf_schema_file);
- qsf_context = xmlSchemaNewValidCtxt(qsf_schema);
- result = xmlSchemaValidateDoc(qsf_context, doc);
- xmlSchemaFreeParserCtxt(qsf_schema_file);
- xmlSchemaFreeValidCtxt(qsf_context);
- xmlSchemaFree(qsf_schema);
- if(result == 0) { return TRUE; }
- return FALSE;
-}
-
-void
-qsf_valid_foreach(xmlNodePtr parent, qsf_validCB cb,
- struct qsf_node_iterate *iter, qsf_validator *valid)
-{
- xmlNodePtr cur_node;
-
- iter->v_fcn = &cb;
- for(cur_node = parent->children; cur_node != NULL; cur_node = cur_node->next)
- {
- cb(cur_node, iter->ns, valid);
- }
-}
-
-void
-qsf_node_foreach(xmlNodePtr parent, qsf_nodeCB cb,
- struct qsf_node_iterate *iter, qsf_param *params)
-{
- xmlNodePtr cur_node;
-
- iter->fcn = &cb;
- for(cur_node = parent->children; cur_node != NULL; cur_node = cur_node->next)
- {
- cb(cur_node, iter->ns, params);
- }
-}
-
-void
-qsf_object_validation_handler(xmlNodePtr child, xmlNsPtr ns, qsf_validator *valid)
-{
- xmlNodePtr cur_node;
- xmlChar *object_declaration;
- guint count;
-
- count = 0;
- for(cur_node = child->children; cur_node != NULL;
- cur_node = cur_node->next)
- {
- if(qsf_is_element(cur_node, ns, QSF_OBJECT_TAG)) {
- object_declaration = xmlGetProp(cur_node, BAD_CAST QSF_OBJECT_TYPE);
- count = g_hash_table_size(valid->validation_table);
- g_hash_table_insert(valid->validation_table, object_declaration, xmlNodeGetContent(cur_node));
- if(g_hash_table_size(valid->validation_table) > count)
- {
- valid->valid_object_count++;
- if(TRUE == qof_class_is_registered((QofIdTypeConst) object_declaration))
- {
- valid->qof_registered_count++;
- }
- }
- }
- }
-}
-
-gboolean is_our_qsf_object(const char *path)
-{
- xmlDocPtr doc;
- struct qsf_node_iterate iter;
- xmlNodePtr object_root;
- qsf_validator valid;
- gint table_count;
-
- g_return_val_if_fail((path != NULL),FALSE);
- doc = xmlParseFile(path);
- if(doc == NULL) { return FALSE; }
- if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc)) {
- PINFO (" validation failed %s %s %s", QSF_SCHEMA_DIR,
- QSF_OBJECT_SCHEMA, path);
- return FALSE;
- }
- object_root = xmlDocGetRootElement(doc);
- valid.validation_table = g_hash_table_new(g_str_hash, g_str_equal);
- valid.qof_registered_count = 0;
- valid.valid_object_count = 0;
- iter.ns = object_root->ns;
- qsf_valid_foreach(object_root, qsf_object_validation_handler, &iter, &valid);
- table_count = g_hash_table_size(valid.validation_table);
- g_hash_table_destroy(valid.validation_table);
- if(table_count == valid.qof_registered_count) { return TRUE; }
- return FALSE;
-}
-
-gboolean is_qsf_object(const char *path)
-{
- xmlDocPtr doc;
-
- g_return_val_if_fail((path != NULL),FALSE);
- if(path == NULL) { return FALSE; }
- doc = xmlParseFile(path);
- if(doc == NULL) { return FALSE; }
- if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc)) { return FALSE; }
- /** \todo implement a way of finding more than one map */
- return is_qsf_object_with_map(path, "pilot-qsf-GnuCashInvoice.xml");
-}
-
-gboolean is_our_qsf_object_be(qsf_param *params)
-{
- xmlDocPtr doc;
- struct qsf_node_iterate iter;
- xmlNodePtr object_root;
- qsf_validator valid;
- gint table_count;
- char *path;
-
- g_return_val_if_fail((params != NULL),FALSE);
- path = g_strdup(params->filepath);
- if(path == NULL) {
- qof_backend_set_error(params->be, ERR_FILEIO_FILE_NOT_FOUND);
- return FALSE;
- }
- if(params->file_type != QSF_UNDEF) { return FALSE; }
- doc = xmlParseFile(path);
- if(doc == NULL) {
- qof_backend_set_error(params->be, ERR_FILEIO_PARSE_ERROR);
- return FALSE;
- }
- if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc))
- {
- qof_backend_set_error(params->be, ERR_QSF_INVALID_OBJ);
- return FALSE;
- }
- params->file_type = IS_QSF_OBJ;
- object_root = xmlDocGetRootElement(doc);
- valid.validation_table = g_hash_table_new(g_str_hash, g_str_equal);
- valid.qof_registered_count = 0;
- iter.ns = object_root->ns;
- qsf_valid_foreach(object_root, qsf_object_validation_handler, &iter, &valid);
- table_count = g_hash_table_size(valid.validation_table);
- if(table_count == valid.qof_registered_count)
- {
- g_hash_table_destroy(valid.validation_table);
- qof_backend_set_error(params->be, ERR_BACKEND_NO_ERR);
- return TRUE;
- }
- g_hash_table_destroy(valid.validation_table);
- qof_backend_set_error(params->be, ERR_QSF_NO_MAP);
- return FALSE;
-}
-
-gboolean is_qsf_object_be(qsf_param *params)
-{
- xmlDocPtr doc;
- char *path;
-
- g_return_val_if_fail((params != NULL),FALSE);
- path = g_strdup(params->filepath);
- if(path == NULL) {
- qof_backend_set_error(params->be, ERR_FILEIO_FILE_NOT_FOUND);
- return FALSE;
- }
- /* skip validation if is_our_qsf_object has already been called. */
- if(ERR_QSF_INVALID_OBJ == qof_backend_get_error(params->be)) { return FALSE; }
- if(params->file_type == QSF_UNDEF)
- {
- doc = xmlParseFile(path);
- if(doc == NULL) {
- qof_backend_set_error(params->be, ERR_FILEIO_PARSE_ERROR);
- return FALSE;
- }
- if(TRUE != qsf_is_valid(QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, doc))
- {
- qof_backend_set_error(params->be, ERR_QSF_INVALID_OBJ);
- return FALSE;
- }
- }
- /** \todo implement a way of finding more than one map */
- return is_qsf_object_with_map_be("pilot-qsf-GnuCashInvoice.xml", params);
-}
-
-static void
-qsf_supported_data_types(gpointer type, gpointer user_data)
-{
- qsf_param *params;
-
- g_return_if_fail(user_data != NULL);
- g_return_if_fail(type != NULL);
- params = (qsf_param*) user_data;
- if(qsf_is_element(params->param_node, params->qsf_ns, (char*)type))
- {
- g_hash_table_insert(params->qsf_parameter_hash,
- xmlGetProp(params->param_node, BAD_CAST QSF_OBJECT_TYPE), params->param_node);
- }
-}
-
-static void
-qsf_parameter_handler(xmlNodePtr child, xmlNsPtr qsf_ns, qsf_param *params)
-{
- params->param_node = child;
- g_slist_foreach(params->supported_types, qsf_supported_data_types, params);
-}
-
-/* Despite the name, this function handles the QSF object book tag
-AND the object tags. */
-void
-qsf_object_node_handler(xmlNodePtr child, xmlNsPtr qsf_ns, qsf_param *params)
-{
- struct qsf_node_iterate iter;
- qsf_objects *object_set;
- char *tail, *object_count_s;
- int c;
-
- g_return_if_fail(child != NULL);
- g_return_if_fail(qsf_ns != NULL);
- params->qsf_ns = qsf_ns;
- if(qsf_is_element(child, qsf_ns, QSF_OBJECT_TAG)) {
- params->qsf_parameter_hash = NULL;
- object_set = g_new(qsf_objects, 1);
- params->object_set = object_set;
- object_set->parameters = g_hash_table_new(g_str_hash, g_str_equal);
- object_set->object_type = g_strdup((char*)xmlGetProp(child, BAD_CAST QSF_OBJECT_TYPE));
- object_count_s = g_strdup((char*)xmlGetProp(child, BAD_CAST QSF_OBJECT_COUNT));
- c = (int)strtol(object_count_s, &tail, 0);
- g_free(object_count_s);
- params->qsf_object_list = g_list_prepend(params->qsf_object_list, object_set);
- iter.ns = qsf_ns;
- params->qsf_parameter_hash = object_set->parameters;
- qsf_node_foreach(child, qsf_parameter_handler, &iter, params);
- }
-}
-
-void
-qsf_book_node_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params)
-{
- char *book_count_s, *tail;
- int book_count;
- xmlNodePtr child_node;
- struct qsf_node_iterate iter;
- gchar *buffer;
- GUID book_guid;
-
- if(qsf_is_element(child, ns, QSF_BOOK_TAG)) {
- book_count_s = (char*)xmlGetProp(child, BAD_CAST QSF_BOOK_COUNT);
- if(book_count_s) {
- book_count = (int)strtol(book_count_s, &tail, 0);
- /* More than one book not currently supported. */
- g_return_if_fail(book_count == 1);
- }
- iter.ns = ns;
- qsf_node_foreach(child, qsf_object_node_handler, &iter, params);
- }
- for(child_node = child->children; child_node != NULL;
- child_node = child_node->next)
- {
- if(qsf_is_element(child_node, ns, QSF_BOOK_GUID)) {
- buffer = g_strdup((char*)xmlNodeGetContent(child_node));
- g_return_if_fail(TRUE == string_to_guid(buffer, &book_guid));
- qof_entity_set_guid((QofEntity*)params->book, &book_guid);
- g_free(buffer);
- }
- if(qsf_is_element(child_node, ns, QSF_OBJECT_TAG)) {
- iter.ns = ns;
- qsf_node_foreach(child_node, qsf_object_node_handler, &iter, params);
- }
- }
-}
Deleted: gnucash/trunk/src/backend/qsf/qsf-xml.h
===================================================================
--- gnucash/trunk/src/backend/qsf/qsf-xml.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/backend/qsf/qsf-xml.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,852 +0,0 @@
-/***************************************************************************
- * qsf-xml.h
- *
- * Fri Nov 26 19:29:47 2004
- * Copyright 2004-2005 Neil Williams <linux at codehelp.co.uk>
- *
- ****************************************************************************/
-/*
- * 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 Library General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
- #ifndef QSF_XML_H
- #define QSF_XML_H
-
-/** @file qsf-xml.h
- @brief Private QSF header
- @author Copyright (C) 2004-2005 Neil Williams <linux at codehelp.co.uk>
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <glib.h>
-#include <regex.h>
-#include <time.h>
-#include <libxml/xmlmemory.h>
-#include <libxml/tree.h>
-#include <libxml/parser.h>
-#include <libxml/xmlschemas.h>
-#include "gnc-date.h"
-#include "qof_book_merge.h"
-#include "qofbook.h"
-#include "qofclass.h"
-#include "qofobject.h"
-#include "kvp_frame.h"
-#include "qofbackend-p.h"
-#include "qofsession-p.h"
-#include "qofbook-p.h"
-
-#if defined(HAVE_GETTEXT) /* HAVE_GETTEXT */
-
-#include <libintl.h>
-#include <locale.h>
-
-#undef _
-#undef Q_
-
-#ifdef DISABLE_GETTEXT_UNDERSCORE
-#define _(String) (String)
-#define Q_(String) gnc_qualifier_prefix_noop(String)
-#else /* ENABLE_GETTEXT_UNDERSCORE */
-#define _(String) gettext(String)
-#define Q_(String) gnc_qualifier_prefix_gettext(String)
-#endif /* End ENABLE_GETTEXT_UNDERSCORE */
-
-#else /* Not HAVE_GETTEXT */
-#if !defined(__USE_GNU_GETTEXT)
-
-#undef _
-#undef Q_
-#define _(String) (String)
-#define Q_(String) gnc_qualifier_prefix_noop(String)
-#define gettext(String) (String)
-#define ngettext(msgid, msgid_plural, n) (((n)==1) ? \
- (msgid) : (msgid_plural))
-
-#endif /* End not__USE_GNU_GETTEXT */
-#endif /* End Not HAVE_GETTEXT */
-
-#undef N_
-#define N_(String) (String)
-
-
-typedef enum {
- QSF_UNDEF = 0, /**< Initial undefined value. */
- IS_QSF_MAP, /**< A QSF map */
- IS_QSF_OBJ, /**< A QSF object without a map - it may or may not need one. */
- HAVE_QSF_MAP, /**< A QSF object with the map it needs. */
- OUR_QSF_OBJ, /**< A QSF object that can be loaded without a map. */
-}qsf_type;
-
-/** \brief Holds a description of the QofObject.
-
-Used when converting QOF objects from another application. The incoming,
-\b unknown, objects need to be stored prior to conversion. This allows
-many-to-many conversions where an invoice can receive data from an incoming
-expense AND datebook and use data from an incoming contacts object to lookup
-the customer for the invoice.
-*/
-typedef struct qsf_object_set
-{
- GHashTable *parameters;
- QofIdType object_type;
- int object_count;
-}qsf_objects;
-
-#define QSF_QOF_VERSION QOF_OBJECT_VERSION /**< QOF Version check.
-
-Make sure the same version of QOF is in use in both applications.
-*/
-/** @name QSF Object XML
-
-@{ */
-#define QSF_ROOT_TAG "qof-qsf" /**< The top level root tag */
-#define QSF_DEFAULT_NS "http://qof.sourceforge.net/" /**< Default namespace for QSF root tag
-
-The map namespace is not included as maps are not currently written out by QOF.
-*/
-#define QSF_DATE_LENGTH 31 /**< Max length of QSF_XSD_TIME */
-#define QSF_BOOK_TAG "book" /**< First level child: book tag - the ::QofBook. */
-#define QSF_BOOK_GUID "book-guid" /**< QOF GUID tag for the QofBook described by this QSF object file */
-#define QSF_BOOK_COUNT "count" /**< Sequential counter of each book in this file */
-#define QSF_OBJECT_TAG "object" /**< Second level child: object tag */
-#define QSF_OBJECT_TYPE "type" /**< QSF parameter name for object type specifiers */
-#define QSF_OBJECT_COUNT "count" /**< Sequential counter for each QSF object in this file */
-#define QSF_XML_VERSION "1.0" /**< The current XML version. */
-
-/** @} */
-/** @name Representing KVP as XML
-
-<kvp type="kvp" path="/from-sched-xaction" value="guid">c858b9a3235723b55bc1179f0e8c1322</kvp>
-A kvp type KVP parameter located at $path containing a GUID $value.
-
-The relevance of type="kvp" won't be evident in GnuCash, they all use "kvp".
-
-A non-GnuCash example helps:
-<kvp type="pilot_addr_kvp" path="/user/name" value="guid">c858b9a3235723b55bc1179f0e8c1322</kvp>
-A pilot_addr_kvp type KVP parameter located at /user/name containing a guid value.
-@{ */
-
-#define QSF_OBJECT_KVP "path" /**< The path to this KVP value in the entity frame. */
-#define QSF_OBJECT_VALUE "value" /**< The KVP Value. */
-/** @} */
-/** @name QSF Map XML
-
-@{ */
-#define MAP_ROOT_TAG "qsf-map" /**< Top level root tag for QSF Maps */
-#define MAP_DEFINITION_TAG "definition" /**< Second level container for defined objects
-
-Attributes: qof_version - Taken from the QOF_OBJECT_VERSION macro in QOF,
-At the time of QSF development, QOF_OBJECT_VERSION is defined as 3. All
-QSF maps and QSF objects must use the same qof_version which in turn must
-match the QOF_OBJECT_VERSION for the QOF library in use by the calling process.
-
-No text content allowed.
-*/
-#define MAP_DEFINE_TAG "define" /**< defines each object supported by this QSF map
-
-Attributes: e_type Copied directly from the QofObject definition.
-Content: The full QofObject description for the defined QOF object.
-*/
-#define MAP_DEFAULT_TAG "default" /**< User editable defaults for data not available within the
-available QSF objects.
-
-Some defaults will relate to how to format descriptive dates, whether discount should be considered,
-which account to use for certain QSF data from applications that don't use accounts.
-
-Some defaults are pre-defined and cannot be over-written:
-- qsf_time_now
-- qsf_time_string
-
-Attributes (All are mandatory):
-
-\a name The text name for this default. Certain pre-defined defaults exist but user- or
-map-defined defaults can have any unique text name. Spaces are \b NOT allowed, use undersccores
-instead. The value of name must not duplicate any existing default, define, object or parameter
-unless the special type, enum, is used.
-
-\a type QOF_TYPE - must be one of the recognised QOF data types for the
-qof_version in use or the special type, enum.
-
-\a value Text representation of the required value. For numeric, use the format
-[0-9]?/[0-9]?
-
-\attention Using boolean defaults
-
-A boolean default is not output in the QSF directly, instead the value is
-used in the calculations to modify certain values. If the boolean default
-is set to true, the if statement containing the boolean name will be evaluated. If the boolean
-default is set to false, the corresponding else will be evaluted. Make sure your
-calculations contain an appropriate else statement so that the boolean value
-can be adjusted without invalidating the map!
-
-QSF deals with partial QofBooks - each object is fully described but the
-book does not have to contain any specific object types or have any
-particular structure. To merge partial books into usual QofBook data
-sources, the map must deal with entities that need to be referenced in
-the target QofBook but which simply don't exist in the QofBook used to generate
-the QSF. e.g. pilot-link knows nothing of Accounts yet when QSF creates
-a gncInvoice from qof-datebook, gncInvoice needs to know the GUID of
-certain accounts in the target QofBook. This is handled in the map
-by specifying the name of the account as a default for that map. When imported,
-the QSF QofBackend looks up the object required using the name of
-the parameter to obtain the parameter type. This is the only situation
-where QSF converts between QOF data types. A string description of the
-required object is converted to the GUID for that specific entity. The
-map cannot contain the GUID as it is generic and used by multiple users.
-
-\attention Using enumerators
-- enum types are the only defaults that are allowed to use the same name value more than once.
-- enum types are used to increase the readability of a QSF map.
-- The enum name acts to group the enum values together - in a similar fashion to radio buttons in HTML forms.
-- enum types are used only where the QOF object itself uses an enum type.
-
-e.g. the tax_included enum type allows maps to use the full name of the enum value GNC_TAXINCLUDED_YES,
-instead of the cryptic digit value, 1.
-
-*/
-#define MAP_OBJECT_TAG "object" /**< Contains all the calculations to make one object from others.
-
-Note that creating an object for the import application can involve using data from more than one
-QSF object, as well as defaults and lookups in the import application itself. Conditionals, simple
-arithmetic and date/time formatting options are also available.
-*/
-#define MAP_CALCULATE_TAG "calculate" /**< One calculation for every parameter that needs to be set.
-
-QSF follows the same rule as qof_book_merge. Only if a getter and a setter function are defined for
-a parameter is it available to QSF. If a ::QofAccessFunc and ::QofSetterFunc are both defined
-for any QofObject parameter, that parameter \b MUST be calculated in any map that defines that object.
-*/
-#define MAP_QOF_VERSION "qof_version" /**< This is the QOF_OBJECT_VERSION from QOF.
-
-QSF maps may need to be updated if QOF itself is upgraded. This setting is coded into QOF and
-maps for one version cannot necessarily be used by other versions. At the first release of QSF,
-QOF_OBJECT_VERSION = 3.
-*/
-#define MAP_NAME_ATTR "name" /**< The name of the default setting.
-
-Use this name to refer to the value of this default in the map calculations.
-
-Make sure that the type of this default matches the type of the parameter being set by the
-parent calculation!
-*/
-#define MAP_TYPE_ATTR "type" /**< QSF will NOT convert between QOF types.
-
-QSF will allow a conditional to use a parameter of one type to determine the value from a parameter of
-another type, but the final value assigned \b MUST be of the same type as the parent calculation.
-*/
-#define MAP_VALUE_ATTR "value" /**< The value of the tag, used in defaults and calculations.
-
-The value of a default is a string representation of the value to be inserted into
-the calculation where the default is used.
-
-The value of a calculation is the name of the parameter that will be set by that calculation.
-*/
-#define MAP_E_TYPE "e_type" /**< Validates the objects defined in the map
-
-The e_type will be used to match incoming QSF objects with the relevant QSF map.
-The value of the e_type must be the value of the e_type for that object in the
-originating QOF application. The define tag must contain the value of the description
-of the same object in the same originating QOF application.
-*/
-/** \todo enum is an attempt to make enumerator values descriptive in the maps
-and QSF (possibly). Not working yet. */
-#define MAP_ENUM_TYPE "enum"
-
-/** \brief A specific boolean default for this map.
-*/
-#define QSF_BOOLEAN_DEFAULT "boolean"
-
-#define QSF_CONDITIONAL "if" /**< child of calculate.
-
-Conditionals can reference objects as if within the original application. In operation,
-the map is overlaid across both sets of defined objects, an import object in the source
-application and an output object for the destination object. The current import and output
-QSF objects are therefore always available to the map.
-Conditionals can reference parameter as well as object values.
-*/
-#define QSF_CONDITIONAL_SET "set" /**< Assignment statement
-
-Map assignments can use the native values within the output object. The output object
-must support setting the relevant parameter using the value exactly as given in the map
-because the relevant set() function will be called using this value. This may reduce the
-readability of the map but the relevant application could also be modified to support a more
-readable set function.
-*/
-#define QSF_CONDITIONAL_ELSE "else" /**< Alternative
-
-if(){} else{} is also supported. Nesting of conditionals causes problems for validating the
-final map against any sensible XML Schema and a map that doesn't validate will be rejected.
-When editing conditionals in a QSF map, ALWAYS validate the map using xmllint. If necessary,
-define a variable at the foot of the definitions block, using a similar syntax to a default,
-then use that variable in another conditional
-
-\a variable \a name="my_rate" \a type="numeric" \a value="0/1"
-
-The syntax for xmllint is:
-
-\a xmllint \a --schema \a <schema file> \a <qsf-file>
-
-Use the qsf-object.xsd.xml schema for objects and qsf-map.xsd.xml for map files.
-
-e.g. xmllint --schema qsf-object.xsd.xml --noout qof-qsf.xml
-
-*/
-#define QSF_OPTION "option" /**< enum operator
-
-Not implemented yet - may need to change once work starts.
-Theoretically, option will specify when an enumerator value is in use -
-it is quite possible that it will be unnecessary.
-*/
-
-#define QSF_FORMATTING_OPTION "format" /**< How to format dates/times
-
-When the QSF map uses a date/time value as a \b string, the formatting
-can be adjusted to personal preference. \a format will only be evaluated
-if the calculated parameter is a QOF_TYPE_STRING - any format attributes
-on other data types will be ignored.
- */
-
-/** @} */
-
-#define QSF_XSD_TIME QOF_UTC_DATE_FORMAT /**< xsd:dateTime format in coordinated universal time, UTC.
-
-You can reproduce the string from the GNU/Linux command line using the date utility:
-
-date -u +%Y-%m-%dT%H:%M:%SZ
-
-2004-12-12T23:39:11Z
-
-The datestring must be timezone independent and include all specified fields.
-
-Remember to use gmtime() NOT localtime()!. From the command line, use the -u switch with the
-date command: date -u
-
-To generate a timestamp based on a real time, use the qsf_time_now and qsf_time_string defaults.
-
-qsf_time_now : Format: QOF_TYPE_DATE. The current time taken from the moment the default
-is read into a QSF object at runtime.
-
-qsf_time_string : Format: QOF_TYPE_STRING. The current timestamp taken from the moment the
-default is read into a QSF object at runtime. This form is used when the output parameter
-needs a formatted date string, not an actual date object. The format is determined by the
-optional format attribute of the set tag which takes the same operators as the GNU C Library
-for strftime() and output may therefore be dependent on the locale of the calling process -
-\b take \b care. Default value is %F, used when qsf_time_string is set without the format
-attribute.
-
-Both defaults use UTC.
-
-*/
-#define QSF_XML_BOOLEAN_TEST "true" /**< needs to be lowercase for XML validation */
-
-#define QSF_OBJECT_SCHEMA "qsf-object.xsd.xml" /**< Name of the QSF Object Schema. */
-#define QSF_MAP_SCHEMA "qsf-map.xsd.xml" /**< Name of the QSF Map Schema. */
-/** \brief QSF Parameters
-
-This struct is a catch-all for all parameters required
-for various stages of the process. There are lots of elements
-here that will finally be removed.
-*/
-typedef struct qsf_metadata
-{
- qsf_type file_type; /**< what type of file is being handled */
- qsf_objects *object_set; /**< current object set for qsf_object_list. */
- int count; /**< sequential counter for each object in the book */
- GList *qsf_object_list; /**< list of qsf_objects */
- GSList *qsf_sequence; /**< Parameter list sorted into QSF order */
- GList *referenceList; /**< Table of references, ::QofEntityReference. */
- GHashTable *qsf_parameter_hash; /**< Hashtable of parameters for each object */
- GHashTable *qsf_calculate_hash, *qsf_default_hash, *qsf_define_hash;
- GSList *supported_types; /**< The partial list of QOF types currently supported, in QSF order. */
- xmlDocPtr input_doc, output_doc; /**< Pointers to the input and output xml document(s). */
- /** \todo Review the list of xml nodes in qsf_param and rationalise. */
- xmlNodePtr child_node, cur_node, param_node, output_node, output_root, book_node, lister;
- xmlNsPtr qsf_ns, map_ns; /**< Separate namespaces for QSF objects and QSF maps. */
- const char *qof_type; /**< Holds details of the QOF_TYPE */
- QofIdType qof_obj_type; /**< current QofObject type (e_type) for the parameters. */
- QofEntity *qsf_ent; /**< Current entity in the book. */
- QofBackend *be; /**< the current QofBackend for this operation. */
- gboolean knowntype; /**< detect references by comparing with known QOF types. */
- QofParam *qof_param; /**< used by kvp to handle the frame hash table */
- QofBook *book; /**< the current QofBook.
-
- Theoretically, QSF can handle multiple QofBooks - currently limited to 1.
- */
- int boolean_calculation_done; /**< simple trip once this boolean is complete. */
- char *filepath; /**< Path to the QSF file. */
-}qsf_param;
-
-/** \brief Free the QSF context.
-
-Frees the two GHashTables, the GSList, the output xmlDoc
-and the two xmlNs namespaces.
-*/
-void qsf_free_params(qsf_param *params);
-
-/** \brief Validation metadata
-
-The validation is a separate parse with separate data.
-This may change but it currently saves workload.
-
-\todo Examine ways of making the Validation metadata
-into a sub-set of the main code, not an island on it's own.
-*/
-typedef struct qsf_validates
-{
- QofBackendError error_state;
- const char *object_path;
- const char *map_path;
- GHashTable *validation_table;
- int valid_object_count;
- int map_calculated_count;
- int qof_registered_count;
-}qsf_validator;
-
-
-/** \brief shorthand function
-
-This may look repetitive but each one is used separately
-as well as in a block.
-*/
-int
-qsf_compare_tag_strings(const xmlChar *node_name, char *tag_name);
-
-/** \brief shorthand function
-
-This may look repetitive but each one is used separately
-as well as in a block.
-*/
-int
-qsf_strings_equal(const xmlChar *node_name, char *tag_name);
-
-/** \brief shorthand function
-
-This may look repetitive but each one is used separately
-as well as in a block.
-*/
-int
-qsf_is_element(xmlNodePtr a, xmlNsPtr ns, char *c);
-
-/** \brief shorthand function
-
-This may look repetitive but each one is used separately
-as well as in a block.
-*/
-int
-qsf_check_tag(qsf_param *params, char *qof_type);
-
-/** \brief Checks all incoming objects for QOF registration.
-
-Sums all existing objects in the QSF and counts the number of those
-objects that are also registered with QOF in the host application.
-*/
-void
-qsf_object_validation_handler(xmlNodePtr child, xmlNsPtr ns, qsf_validator *valid);
-
-/** @name Map Checks
-@{
-Check that the map is sufficient for this object.
-
-Map is usable if all input objects are defined in the object file.
-Count define tags, subtract those calculated in the map (defined as objects)
-Check each remaining object e_type and description against the objects
-declared in the object file. Fail if some map objects remain undefined.
-
-not finished - expect noticeable changes.
-
-*/
-void
-qsf_map_validation_handler(xmlNodePtr child, xmlNsPtr ns, qsf_validator *valid);
-
-void
-qsf_map_top_node_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params);
-
-void
-qsf_map_object_handler(xmlNodePtr child, xmlNsPtr ns, qsf_param *params);
-/** @} */
-
-/** \brief Compares an xmlDoc in memory against the schema file.
-
- at param schema_dir set at compile time to $prefix/share/qsf/
- at param schema_filename Either the QSF Object Schema or the QSF Map Schema.
- at param doc The xmlDoc read from the file using libxml2.
-
-Ensure that you call the right schema_filename for the doc in question!
-
-Incorrect validation will result in output to the terminal window.
-
- at return TRUE if the doc validates against the assigned schema, otherwise FALSE.
-*/
-gboolean
-qsf_is_valid(const char *schema_dir, const char* schema_filename, xmlDocPtr doc);
-
-/** \brief Validate a QSF file and identify a suitable QSF map
-
- at param params Pointer to qsf_param context
-
-These functions are in pairs. When called from within a QofSession, the qsf_param
-context will be available. When just determining the type of file, qsf_param is
-not necessary. Use the *_be functions from within the QofBackend and the
-corresponding function in other code.
-
-The file is validated against the QSF object schema, qsf-object.xsd.xml and
-each object described in the file is checked to find out if a suitable QSF
-map exists. Map files are accepted if all objects described in the QSF object
-file are defined in the QSF map.
-
- at return TRUE if the file validates and a QSF map can be found,
-otherwise FALSE.
-*/
-gboolean is_qsf_object_be(qsf_param *params);
-
-/** \brief Validate a QSF file and determine type.
-
- at param params Pointer to qsf_param context
-
-The file is validated against the QSF object schema, qsf-object.xsd.xml and
-each object described in the file is checked to see if it is registered
-with QOF within the QOF environment of the calling process.
-
-Files that pass the test can be imported into the QOF appliction without the need
-for a QSF map.
-
- at return TRUE if the file validates and all objects pass,
-otherwise FALSE.
-*/
-gboolean is_our_qsf_object_be(qsf_param *params);
-
-/** \brief Validate a QSF map file.
-
- at param params Pointer to qsf_param context
-
-The file is validated aginst the QSF map schema, qsf-map.xsd.xsml. This
-function is called by ::is_qsf_object. If called directly, the map file
-is validated and closed with a QofBackend error. QSF maps do not contain
-user data and are used to import QSF object files.
-
- at return TRUE if the map validates, otherwise FALSE.
-*/
-gboolean is_qsf_map_be(qsf_param *params);
-
-/** \brief Validate a QSF file and a selected QSF map
-
- at param map_path Absolute or relative path to the selected QSF map file
- at param params Pointer to qsf_param context
-
-The file is validated against the QSF object schema, qsf-object.xsd.xml and
-each object described in the file is checked to find out if the supplied QSF
-map is suitable. Map files are accepted if all objects described in the QSF object
-file are defined in the QSF map.
-
-\todo Need to code for how to find these files.
-
-
- at return TRUE if the file validates and the supplied QSF map is usable,
-otherwise FALSE.
-*/
-gboolean is_qsf_object_with_map_be(char *map_path, qsf_param *params);
-
-gboolean is_qsf_object_with_map(const char *path, char *map_file);
-
-/** \brief QOF processing routine.
-
-Called by ::qof_session_load if a map is required.
-Accepts QSF_OBJECT.
-
-Checks available QSF maps for match. Only succeeds if a suitable map exists.
-
-*/
-gboolean
-load_qsf_object(QofBook *book, const char *fullpath, qsf_param *params);
-
-/** \brief QOF processing routine.
-
-Called using ::qof_session_load when all objects defined in the
-XML are registered in the current instance of QOF.
-*/
-gboolean
-load_our_qsf_object(QofBook *book, const char *fullpath, qsf_param *params);
-
-/** \brief Book and book-guid node handler.
-
-Reads the book count="" attribute (currently only 1 QofBook is supported per QSF object file)
-Sets the book-guid as the GUID of the current QofBackend QofBook in qsf_param.
-Calls the next handler, qsf_object_node_handler, with the child of the book tag.
-*/
-void qsf_book_node_handler(xmlNodePtr child, xmlNsPtr qsf_ns, qsf_param *params);
-
-/** \brief Commit the QSF object data to a new QofBook.
-
-The parentage of qof_book_merge should be obvious in this function.
-
-Large chunks were just lifted directly from the commit loop and adjusted
-to obtain the data to commit from the xmlNodePtr instead of qof_book_mergeRule. If
-anything, it's easier here because all entities are new, there are no targets.
-
-Unlike qof_book_merge, this routine runs once per parameter within a loop
-that iterates over objects - it does not have a loop of it's own.
-
-All entities are new.
-
-Using the parent of the current node to
-retrieve the type parameter of the parent provides the type parameter of
-the object tag - the e_type of the current QofObject which allows
-qof_class_get_parameter_setter(obj_type, key);
-
- at param key name of the parameter: QofIdType
- at param value xmlNodePtr value->name == QOF_TYPE, content(value) = data to commit.
- at param data qsf_param* - inevitably.
-
-*/
-void qsf_object_commitCB(gpointer key, gpointer value, gpointer data);
-
-/** \brief Convert a string value into KvpValue
-
-Partner to ::kvp_value_to_string. Given the type of KvpValue
-required, attempts to convert the string into that type of
-value.
-
- at param content A string representation of the value, ideally as
- output by kvp_value_to_string.
- at param type KvpValueType of the intended KvpValue
-
- at return KvpValue* or NULL on failure.
-*/
-KvpValue*
-string_to_kvp_value(const char *content, KvpValueType type);
-
-/** \brief Backend init routine.
-
-Sets the sequence of parameters to match the schema and provide a reliable
-parse. Sets the default strings for qsf_enquiry_date, qsf_time_now and
-qsf_time_string.
-
-Filters the parameter list to set each type in this order:
-- QOF_TYPE_STRING
-- QOF_TYPE_GUID
-- QOF_TYPE_BOOLEAN
-- QOF_TYPE_NUMERIC
-- QOF_TYPE_DATE
-- QOF_TYPE_INT32
-- QOF_TYPE_INT64
-- QOF_TYPE_DOUBLE
-- QOF_TYPE_CHAR
-- QOF_TYPE_KVP
-- QOF_TYPE_COLLECT
-- QOF_TYPE_CHOICE
-
-*/
-void qsf_param_init(qsf_param *params);
-
-
-/** \brief map callback
-
-Investigate ways to get the map callback to do both
-the map and the validation tasks.
-**/
-typedef void (* qsf_nodeCB)(xmlNodePtr, xmlNsPtr, qsf_param*);
-
-/** \brief validator callback
-
-\todo The need for separate metadata means a separate callback typedef
- is needed for the validator, but this should be fixed to only need one.
-*/
-typedef void (* qsf_validCB)(xmlNodePtr, xmlNsPtr, qsf_validator*);
-
-
-/** \brief One iterator, two typedefs
-
-\todo resolve the two callbacks in ::qsf_node_iterate into one.
-*/
-struct qsf_node_iterate {
- qsf_nodeCB *fcn;
- qsf_validCB *v_fcn;
- xmlNsPtr ns;
-};
-
-/** \brief Validate a QSF file and identify a suitable QSF map
-
- at param path Absolute or relative path to the file to be validated.
-
-These functions are in pairs. When called from within a QofSession, the qsf_param
-context will be available. When just determining the type of file, qsf_param is
-not necessary. Use the *_be functions from within the QofBackend and the
-corresponding function in other code.
-
-The file is validated against the QSF object schema, qsf-object.xsd.xml and
-each object described in the file is checked to find out if a suitable QSF
-map exists. Map files are accepted if all objects described in the QSF object
-file are defined in the QSF map.
-
- at return TRUE if the file validates and a QSF map can be found,
-otherwise FALSE.
-*/
-gboolean is_qsf_object(const char *path);
-
-/** \brief Validate a QSF file and determine type.
-
- at param path Absolute or relative path to the file to be validated
-
-These functions are in pairs. When called from within a QofSession, the qsf_param
-context will be available. When just determining the type of file, qsf_param is
-not necessary. Use the *_be functions from within the QofBackend and the
-corresponding function in other code.
-
-The file is validated against the QSF object schema, qsf-object.xsd.xml and
-each object described in the file is checked to see if it is registered
-with QOF within the QOF environment of the calling process.
-
-Files that pass the test can be imported into the QOF appliction without the need
-for a QSF map.
-
- at return TRUE if the file validates and all objects pass,
-otherwise FALSE.
-*/
-gboolean is_our_qsf_object(const char *path);
-
-/** \brief Validate a QSF map file.
-
- at param path Absolute or relative path to the file to be validated
-
-These functions are in pairs. When called from within a QofSession, the qsf_param
-context will be available. When just determining the type of file, qsf_param is
-not necessary. Use the *_be functions from within the QofBackend and the
-corresponding function in other code.
-
-The file is validated aginst the QSF map schema, qsf-map.xsd.xsml. This
-function is called by ::is_qsf_object. If called directly, the map file
-is validated and closed, no data is retrieved. QSF maps do not contain
-user data but are used to import QSF object files from other applications.
-
- at return TRUE if the map validates, otherwise FALSE.
-*/
-gboolean is_qsf_map(const char *path);
-
-/** \brief Determine the type of QSF and load it into the QofBook
-
-- is_our_qsf_object, OUR_QSF_OBJ, QSF object file using only QOF objects known to the calling process.
- No map is required.
-- is_qsf_object, IS_QSF_OBJ, QSF object file that may or may not have a QSF map
- to convert external objects. This temporary type will be set to HAVE_QSF_MAP if a suitable
- map exists, or an error value returned: ERR_QSF_NO_MAP, ERR_QSF_BAD_MAP or ERR_QSF_WRONG_MAP
- This allows the calling process to inform the user that the QSF itself is valid but a
- suitable map cannot be found.
-- is_qsf_map, IS_QSF_MAP, QSF map file. In the backend, this generates ERR_QSF_MAP_NOT_OBJ but
- it can be used internally when processing maps to match a QSF object.
-
- at return NULL on error, otherwise a pointer to the QofBook. Use
- the qof_book_merge API to merge the new data into the current
- QofBook.
-*/
-void
-qsf_file_type (QofBackend *be, QofBook *book);
-
-void
-qsf_valid_foreach(xmlNodePtr parent, qsf_validCB cb,
- struct qsf_node_iterate *iter, qsf_validator *valid);
-
-void
-qsf_node_foreach(xmlNodePtr parent, qsf_nodeCB cb,
- struct qsf_node_iterate *iter, qsf_param *params);
-
-/** \brief Loads the QSF into a QofSession, ready to merge.
-
-Loads a QSF object file containing only GnuCash objects
-into a second QofSession.
-
- at param first_session A QofSession pointer to the original session. This
-will become the target of the subsequent qof_book_merge.
-
- at param path Absolute or relative path to the file to be loaded
-
- at return ERR_BACKEND_NO_ERR == 0 on success, otherwise the QofBackendError
- set by the QSFBackend.
-
-\todo Build the qof_book_merge code onto this function if session loads
- properly.
-*/
-QofBackendError
-qof_session_load_our_qsf_object(QofSession *first_session, const char *path);
-
-/** \brief Placeholder so far.
-
-\todo Determine the map to use and convert the QOF objects
-
- Much of the map code is written but there is still work to do.
-*/
-QofBackendError
-qof_session_load_qsf_object(QofSession *first_session, const char *path);
-
-/** \brief Convert between QSF objects
-
-This is the main workhorse of the conversion between QSF objects using
-maps.
-
- at param mapDoc The map document, parsed by libxml2.
- at param qsf_root The top node of the QSF object to be converted using the map.
- at param params The QSF backend parameters.
-
-Each calculation in the map is performed over the child nodes of the
-object tree. A new xmlDoc is created and this is made available to QOF to
-be loaded into the book.
-
-*/
-xmlDocPtr
-qsf_object_convert(xmlDocPtr mapDoc, xmlNodePtr qsf_root, qsf_param *params);
-
-void
-qsf_object_node_handler(xmlNodePtr child, xmlNsPtr qsf_ns, qsf_param *params);
-
-/** \brief Backend routine to write a file or stdout.
-
-This function is used by ::qof_session_save to write any QofBook to QSF,
-any process that can create a new QofSession and populate the QofBook
-with QOF objects can write the data as QSF XML - the book does not need
-an AccountGroup. Remember that only fully \b QOF-compliant objects
-are supported by QSF.
-
-Your QOF objects must have:
- - a create: function in the QofObject definition
- - a foreach: function in the QofObject definition
- - QofParam params[] registered with QOF using
- qof_class_register and containing all necessary parameters
- to reconstruct this object without any further information.
- - Logical distinction between those parameters that should be
- set (have a QofAccessFunc and QofSetterFunc) and those that
- should only be calculated (only a QofAccessFunc).
-
-If you begin your QSF session with ::QOF_STDOUT as the book_id,
-QSF will write to STDOUT - usually a terminal. This is used by QOF
-applications to provide data streaming. If you don't want terminal
-output, take care to check the path given to
-::qof_session_begin - don't try to change it later!
-
-The XML is validated against the QSF object schema before being
-written (to file or stdout).
-
-Check the QofBackendError - don't assume the file is OK.
-
-*/
-void qsf_write_file(QofBackend *be, QofBook *book);
-
-/** \brief Create a new QSF backend.
-*/
-QofBackend* qsf_backend_new(void);
-
-/** @} */
-/** @} */
-
-#endif /* QSF_XML_H */
Modified: gnucash/trunk/src/engine/Makefile.am
===================================================================
--- gnucash/trunk/src/engine/Makefile.am 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/Makefile.am 2005-11-13 13:22:34 UTC (rev 11917)
@@ -12,103 +12,6 @@
${QOF_CFLAGS} \
${GNUCASH_ENGINE_CFLAGS}
-qof_library = \
- gnc-date.c \
- gnc-engine-util.c \
- gnc-numeric.c \
- gnc-event.c \
- gnc-trace.c \
- guid.c \
- kvp_frame.c \
- kvp-util.c \
- md5.c \
- qofbackend.c \
- qofclass.c \
- qofchoice.c \
- qofid.c \
- qofinstance.c \
- qofquery.c \
- qofbook.c \
- qofobject.c \
- qofquerycore.c \
- qofsession.c \
- qof_book_merge.c
-
-qof_headers = \
- gnc-date.h \
- gnc-engine-util.h \
- gnc-numeric.h \
- gnc-event.h \
- gnc-trace.h \
- guid.h \
- kvp_frame.h \
- kvp-util.h \
- kvp-util-p.h \
- qof.h \
- qof-be-utils.h \
- qofbackend.h \
- qofbackend-p.h \
- qofclass.h \
- qofchoice.h \
- qofid.h \
- qofid-p.h \
- qofinstance-p.h \
- qofinstance.h \
- qofquery.h \
- qofbook.h \
- qofobject.h \
- qofquerycore.h \
- qofsession.h \
- qof_book_merge.h
-
-qof_noinst_headers = \
- gnc-event-p.h \
- md5.h \
- qofclass-p.h \
- qofmath128.h \
- qofquery-p.h \
- qofbook-p.h \
- qofobject-p.h \
- qofquerycore-p.h \
- qofsession-p.h \
- qofsql.h
-
-if USE_LIBQOF
-
-lib_LTLIBRARIES = libqof.la
-
-libqof_la_LDFLAGS= -version-info $(LIBQOF_LIBRARY_VERSION)
-
-libqof_la_SOURCES = ${qof_library}
-
-qofincludedir = ${pkgincludedir}
-
-qofinclude_HEADERS = ${qof_headers}
-
-nodist_qofinclude_HEADERS = qofla-dir.h
-
-QOFLIBdir = $(libdir)
-
-qofla-dir.h: qofla-dir.h.in
- rm -f $@.tmp
- sed < $< > $@.tmp \
- -e 's:@-libdir-@:${QOFLIBdir}:g'
- mv $@.tmp $@
-
-qof_builds = qofla-dir.h
-
-else
-
-libqof_la_SOURCES =
-
-qofincludedir = ${pkgincludedir}
-
-qofinclude_HEADERS =
-
-qof_builds =
-
-endif
-
libgncmod_engine_la_SOURCES = \
Account.c \
FreqSpec.c \
@@ -196,8 +99,7 @@
gnc-pricedb-p.h \
gw-engine.h \
gw-kvp.h \
- policy-p.h \
- ${qof_noinst_headers}
+ policy-p.h
noinst_SCRIPTS = iso-currencies-to-c
@@ -239,12 +141,9 @@
extensions.txt \
iso-4217-currencies.scm \
iso-currencies-to-c \
- qofla-dir.h.in \
gncla-dir.h.in \
kvp_doc.txt \
SX-book-p.h \
- ${qof_library} \
- ${qof_headers} \
${gncmod_DATA} \
${gncscm_DATA} \
${gwmod_DATA}
@@ -288,13 +187,12 @@
(gw:generate-wrapset \"gw-kvp\")"
BUILT_SOURCES = \
- ${qof_builds} \
iso-4217-currencies.c \
gw-engine.scm gw-engine.c gw-engine.h \
gw-kvp.scm gw-kvp.c gw-kvp.h gncla-dir.h
DISTCLEANFILES = gnucash g-wrapped .scm-links ${SCM_FILE_LINKS} \
- gw-engine.html gw-kvp.html qofla-dir.h gncla-dir.h
+ gw-engine.html gw-kvp.html gncla-dir.h
gncla-dir.h: gncla-dir.h.in
rm -f $@.tmp
Deleted: gnucash/trunk/src/engine/gnc-date.c
===================================================================
--- gnucash/trunk/src/engine/gnc-date.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/gnc-date.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,1391 +0,0 @@
-/********************************************************************\
- * gnc-date.c -- misc utility functions to handle date and time *
- * *
- * Copyright (C) 1997 Robin D. Clark <rclark at cs.hmc.edu> *
- * Copyright (C) 1998-2000, 20003 Linas Vepstas <linas at linas.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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-#define _GNU_SOURCE
-#define __EXTENSIONS__
-
-#include "config.h"
-
-#include <ctype.h>
-
-#ifdef HAVE_LANGINFO_D_FMT
-#include <langinfo.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include <glib.h>
-
-#include "gnc-date.h"
-#include "gnc-trace.h"
-
-#ifndef HAVE_STRPTIME
-#include "strptime.h"
-#endif
-#ifndef HAVE_LOCALTIME_R
-#include "localtime_r.h"
-#endif
-
-#define NANOS_PER_SECOND 1000000000
-
-#ifdef HAVE_LANGINFO_D_FMT
-# define GNC_D_FMT (nl_langinfo (D_FMT))
-# define GNC_D_T_FMT (nl_langinfo (D_T_FMT))
-# define GNC_T_FMT (nl_langinfo (T_FMT))
-#else
-# define GNC_D_FMT "%Y-%m-%d"
-# define GNC_D_T_FMT "%Y-%m-%d %r"
-# define GNC_T_FMT "%r"
-#endif
-
-
-/* This is now user configured through the gnome options system() */
-static QofDateFormat dateFormat = QOF_DATE_FORMAT_LOCALE;
-static QofDateFormat prevQofDateFormat = QOF_DATE_FORMAT_LOCALE;
-
-/* This static indicates the debugging module that this .o belongs to. */
-static QofLogModule log_module = QOF_MOD_ENGINE;
-
-/********************************************************************\
-\********************************************************************/
-
-const char*
-gnc_date_dateformat_to_string(QofDateFormat format)
-{
- switch (format) {
- case QOF_DATE_FORMAT_US:
- return "us";
- case QOF_DATE_FORMAT_UK:
- return "uk";
- case QOF_DATE_FORMAT_CE:
- return "ce";
- case QOF_DATE_FORMAT_ISO:
- return "iso";
- case QOF_DATE_FORMAT_UTC:
- return "utc";
- case QOF_DATE_FORMAT_LOCALE:
- return "locale";
- case QOF_DATE_FORMAT_CUSTOM:
- return "custom";
- default:
- return NULL;
- }
-}
-
-gboolean
-gnc_date_string_to_dateformat(const char* fmt_str, QofDateFormat *format)
-{
- if (!fmt_str)
- return TRUE;
-
- if (!strcmp(fmt_str, "us"))
- *format = QOF_DATE_FORMAT_US;
- else if (!strcmp(fmt_str, "uk"))
- *format = QOF_DATE_FORMAT_UK;
- else if (!strcmp(fmt_str, "ce"))
- *format = QOF_DATE_FORMAT_CE;
- else if (!strcmp(fmt_str, "utc"))
- *format = QOF_DATE_FORMAT_UTC;
- else if (!strcmp(fmt_str, "iso"))
- *format = QOF_DATE_FORMAT_ISO;
- else if (!strcmp(fmt_str, "locale"))
- *format = QOF_DATE_FORMAT_LOCALE;
- else if (!strcmp(fmt_str, "custom"))
- *format = QOF_DATE_FORMAT_CUSTOM;
- else
- return TRUE;
-
- return FALSE;
-}
-
-
-const char*
-gnc_date_monthformat_to_string(GNCDateMonthFormat format)
-{
- switch (format) {
- case GNCDATE_MONTH_NUMBER:
- return "number";
- case GNCDATE_MONTH_ABBREV:
- return "abbrev";
- case GNCDATE_MONTH_NAME:
- return "name";
- default:
- return NULL;
- }
-}
-
-gboolean
-gnc_date_string_to_monthformat(const char *fmt_str, GNCDateMonthFormat *format)
-{
- if (!fmt_str)
- return TRUE;
-
- if (!strcmp(fmt_str, "number"))
- *format = GNCDATE_MONTH_NUMBER;
- else if (!strcmp(fmt_str, "abbrev"))
- *format = GNCDATE_MONTH_ABBREV;
- else if (!strcmp(fmt_str, "name"))
- *format = GNCDATE_MONTH_NAME;
- else
- return TRUE;
-
- return FALSE;
-}
-
-/********************************************************************\
-\********************************************************************/
-
-static void
-timespec_normalize(Timespec *t)
-{
- if(t->tv_nsec > NANOS_PER_SECOND)
- {
- t->tv_sec+= (t->tv_nsec / NANOS_PER_SECOND);
- t->tv_nsec= t->tv_nsec % NANOS_PER_SECOND;
- }
-
- if(t->tv_nsec < - NANOS_PER_SECOND)
- {
- t->tv_sec+= - (-t->tv_nsec / NANOS_PER_SECOND);
- t->tv_nsec = - (-t->tv_nsec % NANOS_PER_SECOND);
- }
-
- if (t->tv_sec > 0 && t->tv_nsec < 0)
- {
- t->tv_sec--;
- t->tv_nsec = NANOS_PER_SECOND + t->tv_nsec;
- }
-
- if (t->tv_sec < 0 && t->tv_nsec > 0)
- {
- t->tv_sec++;
- t->tv_nsec = - NANOS_PER_SECOND + t->tv_nsec;
- }
- return;
-}
-
-
-gboolean
-timespec_equal (const Timespec *ta, const Timespec *tb)
-{
- if(ta == tb) return TRUE;
- if(ta->tv_sec != tb->tv_sec) return FALSE;
- if(ta->tv_nsec != tb->tv_nsec) return FALSE;
- return TRUE;
-}
-
-gint
-timespec_cmp(const Timespec *ta, const Timespec *tb)
-{
- if(ta == tb) return 0;
- if(ta->tv_sec < tb->tv_sec) return -1;
- if(ta->tv_sec > tb->tv_sec) return 1;
- if(ta->tv_nsec < tb->tv_nsec) return -1;
- if(ta->tv_nsec > tb->tv_nsec) return 1;
- return 0;
-}
-
-Timespec
-timespec_diff(const Timespec *ta, const Timespec *tb)
-{
- Timespec retval;
- retval.tv_sec = ta->tv_sec - tb->tv_sec;
- retval.tv_nsec = ta->tv_nsec - tb->tv_nsec;
- timespec_normalize(&retval);
- return retval;
-}
-
-Timespec
-timespec_abs(const Timespec *t)
-{
- Timespec retval = *t;
-
- timespec_normalize(&retval);
- if (retval.tv_sec < 0)
- {
- retval.tv_sec = - retval.tv_sec;
- retval.tv_nsec = - retval.tv_nsec;
- }
-
- return retval;
-}
-
-/** \brief Converts any time on a day to midday that day.
-
- * given a timepair contains any time on a certain day (local time)
- * converts it to be midday that day.
- */
-
-Timespec
-timespecCanonicalDayTime(Timespec t)
-{
- struct tm tm, *result;
- Timespec retval;
- time_t t_secs = t.tv_sec + (t.tv_nsec / NANOS_PER_SECOND);
- result = localtime(&t_secs);
- tm = *result;
- gnc_tm_set_day_middle(&tm);
- retval.tv_sec = mktime(&tm);
- retval.tv_nsec = 0;
- return retval;
-}
-
-int gnc_date_my_last_mday (int month, int year)
-{
- gboolean is_leap;
- static int days_in_month[2][12] =
- {/* non leap */ {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
- /* leap */ {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
-
- /* Is this a leap year? */
- if (year % 2000 == 0)
- is_leap = TRUE;
- else if (year % 400 == 0)
- is_leap = FALSE;
- else
- is_leap = (year % 4 == 0);
-
- return days_in_month[is_leap][month-1];
-}
-
-/* Retrieve the last numerical day of the month
-
- Retrieve the last numerical day for the month specified in the
- tm_year and tm_mon fields.
-
-param tm: the time value in question
-return the last day of the month, integer.
-*/
-int date_get_last_mday(struct tm *tm)
-{
- return gnc_date_my_last_mday (tm->tm_mon+1, tm->tm_year+1900);
-}
-
-/* Determines if tm_mday is the last day of the month.
-
- Determines whether the tm_mday field contains the last day of the
- month as specified in the tm_year and tm_mon fields.
-param tm: the time value in question
-return TRUE if tm_mday matches the last day of the month, else FALSE.
-*/
-gboolean date_is_last_mday(struct tm *tm)
-{
- return(tm->tm_mday == date_get_last_mday(tm));
-}
-
-/* Add a number of months to a time value
-
- Add a number of months to a time value, and normalize. Optionally
- also track the last day of the month, i.e. 1/31 -> 2/28 -> 3/30.
-
-param tm: base time value
-param months: The number of months to add to this time
-param track_last_day: Coerce the date value if necessary.
-
-return void
-*/
-void date_add_months (struct tm *tm, int months, gboolean track_last_day)
-{
- gboolean was_last_day;
- int new_last_mday;
-
- /* Have to do this now */
- was_last_day = date_is_last_mday(tm);
-
- /* Add in the months and normalize */
- tm->tm_mon += months;
- while (tm->tm_mon > 11) {
- tm->tm_mon -= 12;
- tm->tm_year++;
- }
-
- if (!track_last_day)
- return;
-
- /* Track last day of the month, i.e. 1/31 -> 2/28 -> 3/30 */
- new_last_mday = date_get_last_mday(tm);
- if (was_last_day || (tm->tm_mday > new_last_mday))
- tm->tm_mday = new_last_mday;
-}
-
-/* Return the set dateFormat.
-
-return QofDateFormat: enumeration indicating preferred format
-
-Global: dateFormat
-*/
-QofDateFormat qof_date_format_get (void)
-{
- return dateFormat;
-}
-
-/* set date format
-
-set date format to one of US, UK, CE, ISO OR UTC
-checks to make sure it's a legal value
-
-param QofDateFormat: enumeration indicating preferred format
-
-return void
-
-Globals: dateFormat
-*/
-void qof_date_format_set(QofDateFormat df)
-{
- if(df >= DATE_FORMAT_FIRST && df <= DATE_FORMAT_LAST)
- {
- prevQofDateFormat = dateFormat;
- dateFormat = df;
- }
- else
- { /* hack alert - Use a neutral default. */
- PERR("non-existent date format set attempted. Setting ISO default");
- prevQofDateFormat = dateFormat;
- dateFormat = QOF_DATE_FORMAT_ISO;
- }
-
- return;
-}
-
-/*
- qof_date_format_get_string
- get the date format string for the current format
- returns: string
-
- Globals: dateFormat
-*/
-const gchar *qof_date_format_get_string(QofDateFormat df)
-{
- switch(df) {
- case QOF_DATE_FORMAT_US:
- return "%m/%d/%y";
- case QOF_DATE_FORMAT_UK:
- return "%d/%m/%y";
- case QOF_DATE_FORMAT_CE:
- return "%d.%m.%y";
- case QOF_DATE_FORMAT_UTC:
- return "%Y-%m-%dT%H:%M:%SZ";
- case QOF_DATE_FORMAT_ISO:
- return "%y-%m-%d";
- case QOF_DATE_FORMAT_LOCALE:
- default:
- return GNC_D_FMT;
- };
-}
-
-/* get the date format string for the current format
-
-get the date format string for the current format
-
-param df Required date format.
-return string
-
-Globals: dateFormat
-*/
-const gchar *qof_date_text_format_get_string(QofDateFormat df)
-{
- switch(df) {
- case QOF_DATE_FORMAT_US:
- return "%b %d, %y";
- case QOF_DATE_FORMAT_UK:
- case QOF_DATE_FORMAT_CE:
- return "%d %b, %y";
- case QOF_DATE_FORMAT_UTC:
- return "%Y-%m-%dT%H:%M:%SZ";
- case QOF_DATE_FORMAT_ISO:
- return "%y-%b-%d";
- case QOF_DATE_FORMAT_LOCALE:
- default:
- return GNC_D_FMT;
- };
-}
-
-/* Convert day, month and year values to a date string
-
- Convert a date as day / month / year integers into a localized string
- representation
-
-param buff - pointer to previously allocated character array; its size
- must be at lease MAX_DATE_LENTH bytes.
-param day - value to be set with the day of the month as 1 ... 31
-param month - value to be set with the month of the year as 1 ... 12
-param year - value to be set with the year (4-digit)
-
-return void
-
-Globals: global dateFormat value
-*/
-size_t
-qof_print_date_dmy_buff (char * buff, size_t len, int day, int month, int year)
-{
- int flen;
- if (!buff) return 0;
-
- /* Note that when printing year, we use %-4d in format string;
- * this causes a one, two or three-digit year to be left-adjusted
- * when printed (i.e. padded with blanks on the right). This is
- * important while the user is editing the year, since erasing a
- * digit can temporarily cause a three-digit year, and having the
- * blank on the left is a real pain for the user. So pad on the
- * right.
- */
- switch(dateFormat)
- {
- case QOF_DATE_FORMAT_UK:
- flen = g_snprintf (buff, len, "%2d/%2d/%-4d", day, month, year);
- break;
- case QOF_DATE_FORMAT_CE:
- flen = g_snprintf (buff, len, "%2d.%2d.%-4d", day, month, year);
- break;
- case QOF_DATE_FORMAT_LOCALE:
- {
- struct tm tm_str;
- time_t t;
-
- tm_str.tm_mday = day;
- tm_str.tm_mon = month - 1; /* tm_mon = 0 through 11 */
- tm_str.tm_year = year - 1900; /* this is what the standard
- * says, it's not a Y2K thing */
-
- gnc_tm_set_day_start (&tm_str);
- t = mktime (&tm_str);
- localtime_r (&t, &tm_str);
- flen = strftime (buff, len, GNC_D_FMT, &tm_str);
- if (flen != 0)
- break;
- }
- /* FALLTHROUGH */
- case QOF_DATE_FORMAT_ISO:
- case QOF_DATE_FORMAT_UTC:
- flen = g_snprintf (buff, len, "%04d-%02d-%02d", year, month, day);
- break;
- case QOF_DATE_FORMAT_US:
- default:
- flen = g_snprintf (buff, len, "%2d/%2d/%-4d", month, day, year);
- break;
- }
-
- return flen;
-}
-
-size_t
-qof_print_date_buff (char * buff, size_t len, time_t t)
-{
- struct tm *theTime;
-
- if (!buff) return 0 ;
-
- theTime = localtime (&t);
-
- return qof_print_date_dmy_buff (buff, len,
- theTime->tm_mday,
- theTime->tm_mon + 1,
- theTime->tm_year + 1900);
-}
-
-size_t
-qof_print_gdate( char *buf, size_t len, GDate *gd )
-{
- return qof_print_date_dmy_buff( buf, len,
- g_date_day(gd),
- g_date_month(gd),
- g_date_year(gd) );
-}
-
-char *
-qof_print_date (time_t t)
-{
- char buff[MAX_DATE_LENGTH];
- qof_print_date_buff (buff, MAX_DATE_LENGTH, t);
- return g_strdup (buff);
-}
-
-const char *
-gnc_print_date (Timespec ts)
-{
- static char buff[MAX_DATE_LENGTH];
- time_t t;
-
- t = ts.tv_sec + (ts.tv_nsec / 1000000000.0);
-
- qof_print_date_buff (buff, MAX_DATE_LENGTH, t);
-
- return buff;
-}
-
-/* ============================================================== */
-
-size_t
-qof_print_hours_elapsed_buff (char * buff, size_t len, int secs, gboolean show_secs)
-{
- size_t flen;
- if (0 <= secs)
- {
- if (show_secs)
- {
- flen = g_snprintf(buff, len,
- "%02d:%02d:%02d", (int)(secs / 3600),
- (int)((secs % 3600) / 60), (int)(secs % 60));
- }
- else
- {
- flen = g_snprintf(buff, len,
- "%02d:%02d", (int)(secs / 3600),
- (int)((secs % 3600) / 60));
- }
- }
- else
- {
- if (show_secs)
- {
- flen = g_snprintf(buff, len,
- "-%02d:%02d:%02d", (int)(-secs / 3600),
- (int)((-secs % 3600) / 60), (int)(-secs % 60));
- }
- else
- {
- flen = g_snprintf(buff, len,
- "-%02d:%02d", (int)(-secs / 3600),
- (int)((-secs % 3600) / 60));
- }
- }
- return flen;
-}
-
-/* ============================================================== */
-
-size_t
-qof_print_minutes_elapsed_buff (char * buff, size_t len, int secs, gboolean show_secs)
-{
- size_t flen;
- if (0 <= secs)
- {
- if (show_secs)
- {
- flen = g_snprintf(buff, len,
- "%02d:%02d",
- (int)(secs / 60), (int)(secs % 60));
- }
- else
- {
- flen = g_snprintf(buff, len,
- "%02d", (int)(secs / 60));
- }
- }
- else
- {
- if (show_secs)
- {
- flen = g_snprintf(buff, len,
- "-%02d:%02d", (int)(-secs / 60), (int)(-secs % 60));
- }
- else
- {
- flen = g_snprintf(buff, len,
- "-%02d", (int)(-secs / 60));
- }
- }
- return flen;
-}
-
-/* ============================================================== */
-
-size_t
-qof_print_date_time_buff (char * buff, size_t len, time_t secs)
-{
- int flen;
- int day, month, year, hour, min, sec;
- struct tm ltm, gtm;
-
- if (!buff) return 0;
-
- /* Note that when printing year, we use %-4d in format string;
- * this causes a one, two or three-digit year to be left-adjusted
- * when printed (i.e. padded with blanks on the right). This is
- * important while the user is editing the year, since erasing a
- * digit can temporarily cause a three-digit year, and having the
- * blank on the left is a real pain for the user. So pad on the
- * right.
- */
- ltm = *localtime (&secs);
- day = ltm.tm_mday;
- month = ltm.tm_mon +1;
- year = ltm.tm_year +1900;
- hour = ltm.tm_hour;
- min = ltm.tm_min;
- sec = ltm.tm_sec;
-
- switch(dateFormat)
- {
- case QOF_DATE_FORMAT_UK:
- flen = g_snprintf (buff, len, "%2d/%2d/%-4d %2d:%02d", day, month, year, hour, min);
- break;
- case QOF_DATE_FORMAT_CE:
- flen = g_snprintf (buff, len, "%2d.%2d.%-4d %2d:%02d", day, month, year, hour, min);
- break;
- case QOF_DATE_FORMAT_ISO:
- flen = g_snprintf (buff, len, "%04d-%02d-%02d %02d:%02d", year, month, day, hour, min);
- break;
- case QOF_DATE_FORMAT_UTC:
- {
- gtm = *gmtime (&secs);
- flen = strftime (buff, len, QOF_UTC_DATE_FORMAT, >m);
- break;
- }
- case QOF_DATE_FORMAT_LOCALE:
- {
- flen = strftime (buff, len, GNC_D_T_FMT, <m);
- }
- break;
-
- case QOF_DATE_FORMAT_US:
- default:
- flen = g_snprintf (buff, len, "%2d/%2d/%-4d %2d:%02d", month, day, year, hour, min);
- break;
- }
- return flen;
-}
-
-size_t
-qof_print_time_buff (char * buff, size_t len, time_t secs)
-{
- int flen;
- struct tm ltm, gtm;
-
- if (!buff) return 0;
- if(dateFormat == QOF_DATE_FORMAT_UTC)
- {
- gtm = *gmtime (&secs);
- flen = strftime(buff, len, QOF_UTC_DATE_FORMAT, >m);
- return flen;
- }
- ltm = *localtime (&secs);
- flen = strftime (buff, len, GNC_T_FMT, <m);
-
- return flen;
-}
-
-/* ============================================================== */
-
-int
-qof_is_same_day (time_t ta, time_t tb)
-{
- struct tm lta, ltb;
- lta = *localtime (&ta);
- ltb = *localtime (&tb);
- if (lta.tm_year == ltb.tm_year)
- {
- return (ltb.tm_yday - lta.tm_yday);
- }
- return (ltb.tm_year - lta.tm_year)*365; /* very approximate */
-}
-
-/* ============================================================== */
-
-/* Convert a string into day, month and year integers
-
- Convert a string into day / month / year integers according to
- the current dateFormat value.
-
- This function will always parse a single number as the day of
- the month, regardless of the ordering of the dateFormat value.
- Two numbers will always be parsed as the day and the month, in
- the same order that they appear in the dateFormat value. Three
- numbers are parsed exactly as specified in the dateFormat field.
-
- Fully formatted UTC timestamp strings are converted separately.
-
-param buff - pointer to date string
-param day - will store day of the month as 1 ... 31
-param month - will store month of the year as 1 ... 12
-param year - will store the year (4-digit)
-
-return TRUE if date appeared to be valid.
-
- Globals: global dateFormat value
-*/
-static gboolean
-qof_scan_date_internal (const char *buff, int *day, int *month, int *year,
- QofDateFormat which_format)
-{
- char *dupe, *tmp, *first_field, *second_field, *third_field;
- int iday, imonth, iyear;
- struct tm *now, utc;
- time_t secs;
-
- if (!buff) return(FALSE);
-
- if(which_format == QOF_DATE_FORMAT_UTC)
- {
- if(strptime(buff, QOF_UTC_DATE_FORMAT, &utc)) {
- *day = utc.tm_mday;
- *month = utc.tm_mon + 1;
- *year = utc.tm_year + 1900;
- return TRUE;
- }
- else { return FALSE; }
- }
- dupe = g_strdup (buff);
-
- tmp = dupe;
- first_field = NULL;
- second_field = NULL;
- third_field = NULL;
-
- /* Use strtok to find delimiters */
- if (tmp) {
- static char *delims = ".,-+/\\() ";
-
- first_field = strtok (tmp, delims);
- if (first_field) {
- second_field = strtok (NULL, delims);
- if (second_field) {
- third_field = strtok (NULL, delims);
- }
- }
- }
-
- /* If any fields appear to be blank, use today's date */
- time (&secs);
- now = localtime (&secs);
- iday = now->tm_mday;
- imonth = now->tm_mon+1;
- iyear = now->tm_year+1900;
-
- /* get numeric values */
- switch (which_format)
- {
- case QOF_DATE_FORMAT_LOCALE:
- if (buff[0] != '\0')
- {
- struct tm thetime;
-
- /* Parse time string. */
- memset(&thetime, -1, sizeof(struct tm));
- strptime (buff, GNC_D_FMT, &thetime);
-
- if (third_field) {
- /* Easy. All three values were parsed. */
- iyear = thetime.tm_year + 1900;
- iday = thetime.tm_mday;
- imonth = thetime.tm_mon + 1;
- } else if (second_field) {
- /* Hard. Two values parsed. Figure out the ordering. */
- if (thetime.tm_year == -1) {
- /* %m-%d or %d-%m. Don't care. Already parsed correctly. */
- iday = thetime.tm_mday;
- imonth = thetime.tm_mon + 1;
- } else if (thetime.tm_mon != -1) {
- /* Must be %Y-%m-%d. Reparse as %m-%d.*/
- imonth = atoi(first_field);
- iday = atoi(second_field);
- } else {
- /* Must be %Y-%d-%m. Reparse as %d-%m. */
- iday = atoi(first_field);
- imonth = atoi(second_field);
- }
- } else if (first_field) {
- iday = atoi(first_field);
- }
- }
- break;
- case QOF_DATE_FORMAT_UK:
- case QOF_DATE_FORMAT_CE:
- if (third_field) {
- iday = atoi(first_field);
- imonth = atoi(second_field);
- iyear = atoi(third_field);
- } else if (second_field) {
- iday = atoi(first_field);
- imonth = atoi(second_field);
- } else if (first_field) {
- iday = atoi(first_field);
- }
- break;
- case QOF_DATE_FORMAT_ISO:
- if (third_field) {
- iyear = atoi(first_field);
- imonth = atoi(second_field);
- iday = atoi(third_field);
- } else if (second_field) {
- imonth = atoi(first_field);
- iday = atoi(second_field);
- } else if (first_field) {
- iday = atoi(first_field);
- }
- break;
- case QOF_DATE_FORMAT_US:
- default:
- if (third_field) {
- imonth = atoi(first_field);
- iday = atoi(second_field);
- iyear = atoi(third_field);
- } else if (second_field) {
- imonth = atoi(first_field);
- iday = atoi(second_field);
- } else if (first_field) {
- iday = atoi(first_field);
- }
- break;
- }
-
- g_free (dupe);
-
- if ((12 < imonth) || (31 < iday))
- {
- /*
- * Ack! Thppfft! Someone just fed this routine a string in the
- * wrong date format. This is known to happen if a register
- * window is open when changing the date format. Try the
- * previous date format. If that doesn't work, see if we can
- * exchange month and day. If that still doesn't work,
- * bail and give the caller what they asked for (garbage)
- * parsed in the new format.
- *
- * Note: This test cannot detect any format change that only
- * swaps month and day field, if the day is 12 or less. This is
- * deemed acceptable given the obscurity of this bug.
- */
- if ((which_format != prevQofDateFormat) &&
- qof_scan_date_internal(buff, day, month, year, prevQofDateFormat))
- {
- return(TRUE);
- }
- if ((12 < imonth) && (12 >= iday))
- {
- int tmp = imonth; imonth = iday; iday = tmp;
- }
- else
- {
- return FALSE;
- }
- }
-
- /* If the year entered is smaller than 100, assume we mean the current
- century (and are not revising some roman emperor's books) */
- if (iyear < 100)
- iyear += ((int) ((now->tm_year+1950-iyear)/100)) * 100;
-
- if (year) *year=iyear;
- if (month) *month=imonth;
- if (day) *day=iday;
- return(TRUE);
-}
-
-gboolean
-qof_scan_date (const char *buff, int *day, int *month, int *year)
-{
- return qof_scan_date_internal(buff, day, month, year, dateFormat);
-}
-
-gboolean
-qof_scan_date_secs (const char *buff, time_t *secs)
-{
- gboolean rc;
- int day, month, year;
-
- rc = qof_scan_date_internal(buff, &day, &month, &year, dateFormat);
- if (secs) *secs = xaccDMYToSec (day, month, year);
-
- return rc;
-}
-
-/* Return the field separator for the current date format
-return date character
-*/
-char dateSeparator (void)
-{
- static char locale_separator = '\0';
-
- switch (dateFormat)
- {
- case QOF_DATE_FORMAT_CE:
- return '.';
- case QOF_DATE_FORMAT_ISO:
- case QOF_DATE_FORMAT_UTC:
- return '-';
- case QOF_DATE_FORMAT_US:
- case QOF_DATE_FORMAT_UK:
- default:
- return '/';
- case QOF_DATE_FORMAT_LOCALE:
- if (locale_separator != '\0')
- return locale_separator;
- else
- { /* Make a guess */
- char string[256];
- struct tm *tm;
- time_t secs;
- char *s;
-
- secs = time(NULL);
- tm = localtime(&secs);
- strftime(string, sizeof(string), GNC_D_FMT, tm);
-
- for (s = string; s != '\0'; s++)
- if (!isdigit(*s))
- return (locale_separator = *s);
- }
- }
-
- return '\0';
-}
-
-/********************************************************************\
-\********************************************************************/
-
-/* Convert time in seconds to a textual.
-
-The xaccDateUtilGetStamp() routine will take the given time in
-seconds and return a buffer containing a textual for the date.
-
-param thyme The time in seconds to convert.
-return A pointer to the generated string.
-The caller owns this buffer and must free it when done.
-*/
-char *
-xaccDateUtilGetStamp (time_t thyme)
-{
- struct tm *stm;
-
- stm = localtime (&thyme);
-
- return g_strdup_printf("%04d%02d%02d%02d%02d%02d",
- (stm->tm_year + 1900),
- (stm->tm_mon +1),
- stm->tm_mday,
- stm->tm_hour,
- stm->tm_min,
- stm->tm_sec
- );
-}
-
-
-/* Convert textual to time in seconds.
-
-The xaccDateUtilGetStampNow() routine returns the current time in
-seconds in textual format.
-
-return A pointer to the generated string.
-
-note The caller owns this buffer and must free it when done.
-*/
-char *
-xaccDateUtilGetStampNow (void)
-{
- time_t now;
- time (&now);
- return xaccDateUtilGetStamp (now);
-}
-
-/********************************************************************\
- * iso 8601 datetimes should look like 1998-07-02 11:00:00.68-05
-\********************************************************************/
-/* hack alert -- this routine returns incorrect values for
- * dates before 1970 */
-
-Timespec
-gnc_iso8601_to_timespec_gmt(const char *str)
-{
- char buf[4];
- Timespec ts;
- struct tm stm;
- long int nsec =0;
-
- ts.tv_sec=0;
- ts.tv_nsec=0;
- if (!str) return ts;
-
- stm.tm_year = atoi(str) - 1900;
- str = strchr (str, '-'); if (str) { str++; } else { return ts; }
- stm.tm_mon = atoi(str) - 1;
- str = strchr (str, '-'); if (str) { str++; } else { return ts; }
- stm.tm_mday = atoi(str);
-
- str = strchr (str, ' '); if (str) { str++; } else { return ts; }
- stm.tm_hour = atoi(str);
- str = strchr (str, ':'); if (str) { str++; } else { return ts; }
- stm.tm_min = atoi(str);
- str = strchr (str, ':'); if (str) { str++; } else { return ts; }
- stm.tm_sec = atoi (str);
-
- /* The decimal point, optionally present ... */
- /* hack alert -- this algo breaks if more than 9 decimal places present */
- if (strchr (str, '.'))
- {
- int decimals, i, multiplier=1000000000;
- str = strchr (str, '.') +1;
- decimals = strcspn (str, "+- ");
- for (i=0; i<decimals; i++) multiplier /= 10;
- nsec = atoi(str) * multiplier;
- }
- stm.tm_isdst = -1;
-
- /* Timezone format can be +hh or +hhmm or +hh.mm (or -) (or not present) */
- str += strcspn (str, "+-");
- if (str)
- {
- buf[0] = str[0];
- buf[1] = str[1];
- buf[2] = str[2];
- buf[3] = 0;
- stm.tm_hour -= atoi(buf);
-
- str +=3;
- if ('.' == *str) str++;
- if (isdigit (*str) && isdigit (*(str+1)))
- {
- int cyn;
- /* copy sign from hour part */
- if ('+' == buf[0]) { cyn = -1; } else { cyn = +1; }
- buf[0] = str[0];
- buf[1] = str[1];
- buf[2] = str[2];
- buf[3] = 0;
- stm.tm_min += cyn * atoi(buf);
- }
- }
-
- /* Note that mktime returns 'local seconds' which is the true time
- * minus the timezone offset. We don't want to work with local
- * seconds, since they swim around acording to daylight savings, etc.
- * We want to work with universal time. Thus, add an offset
- * to undo the damage that mktime causes.
- */
- {
- struct tm tmp_tm;
- struct tm *tm;
- long int tz;
- int tz_hour;
- time_t secs;
-
- /* Use a temporary tm struct so the mktime call below
- * doesn't mess up stm. */
- tmp_tm = stm;
- tmp_tm.tm_isdst = -1;
-
- secs = mktime (&tmp_tm);
-
- /* The call to localtime is 'bogus', but it forces 'timezone' to
- * be set. Note that we must use the accurate date, since the
- * value of 'gnc_timezone' includes daylight savings corrections
- * for that date. */
- tm = localtime (&secs);
-
- tz = gnc_timezone (tm);
-
- tz_hour = tz / 3600;
- stm.tm_hour -= tz_hour;
- stm.tm_min -= (tz - (3600 * tz_hour)) / 60;
- stm.tm_isdst = tmp_tm.tm_isdst;
- }
-
- ts.tv_sec = mktime (&stm);
- ts.tv_nsec = nsec;
-
- return ts;
-}
-
-/********************************************************************\
-\********************************************************************/
-
-char *
-gnc_timespec_to_iso8601_buff (Timespec ts, char * buff)
-{
- int len;
- int tz_hour, tz_min;
- char cyn;
- time_t tmp;
- struct tm parsed;
-
- tmp = ts.tv_sec;
- localtime_r(&tmp, &parsed);
-
- tz_hour = gnc_timezone (&parsed) / 3600;
- tz_min = (gnc_timezone (&parsed) - 3600*tz_hour) / 60;
- if (0>tz_min) { tz_min +=60; tz_hour --; }
- if (60<=tz_min) { tz_min -=60; tz_hour ++; }
-
- /* We also have to print the sign by hand, to work around a bug
- * in the glibc 2.1.3 printf (where %+02d fails to zero-pad).
- */
- cyn = '-';
- if (0>tz_hour) { cyn = '+'; tz_hour = -tz_hour; }
-
- len = sprintf (buff, "%4d-%02d-%02d %02d:%02d:%02d.%06ld %c%02d%02d",
- parsed.tm_year + 1900,
- parsed.tm_mon + 1,
- parsed.tm_mday,
- parsed.tm_hour,
- parsed.tm_min,
- parsed.tm_sec,
- ts.tv_nsec / 1000,
- cyn,
- tz_hour,
- tz_min);
-
- /* Return pointer to end of string. */
- buff += len;
- return buff;
-}
-
-int
-gnc_timespec_last_mday (Timespec t)
-{
- struct tm *result;
- time_t t_secs = t.tv_sec + (t.tv_nsec / NANOS_PER_SECOND);
- result = localtime(&t_secs);
- return date_get_last_mday (result);
-}
-
-void
-gnc_timespec2dmy (Timespec t, int *day, int *month, int *year)
-{
- struct tm *result;
- time_t t_secs = t.tv_sec + (t.tv_nsec / NANOS_PER_SECOND);
- result = localtime(&t_secs);
-
- if (day) *day = result->tm_mday;
- if (month) *month = result->tm_mon+1;
- if (year) *year = result->tm_year+1900;
-}
-
-/********************************************************************\
-\********************************************************************/
-/* hack alert -- this routine returns incorrect values for
- * dates before 1970 */
-
-time_t
-xaccDMYToSec (int day, int month, int year)
-{
- struct tm stm;
- time_t secs;
-
- stm.tm_year = year - 1900;
- stm.tm_mon = month - 1;
- stm.tm_mday = day;
- gnc_tm_set_day_start(&stm);
-
- /* compute number of seconds */
- secs = mktime (&stm);
-
- return secs;
-}
-
-
-#define THIRTY_TWO_YEARS 0x3c30fc00LL
-
-static Timespec
-gnc_dmy2timespec_internal (int day, int month, int year, gboolean start_of_day)
-{
- Timespec result;
- struct tm date;
- long long secs = 0;
- long long era = 0;
-
- year -= 1900;
-
- /* make a crude attempt to deal with dates outside the range of Dec
- * 1901 to Jan 2038. Note we screw up centennial leap years here so
- * hack alert */
- if ((2 > year) || (136 < year))
- {
- era = year / 32;
- year %= 32;
- if (0 > year) { year += 32; era -= 1; }
- }
-
- date.tm_year = year;
- date.tm_mon = month - 1;
- date.tm_mday = day;
-
- if (start_of_day)
- gnc_tm_set_day_start(&date);
- else
- gnc_tm_set_day_end(&date);
-
- /* compute number of seconds */
- secs = mktime (&date);
-
- secs += era * THIRTY_TWO_YEARS;
-
- result.tv_sec = secs;
- result.tv_nsec = 0;
-
- return result;
-}
-
-Timespec
-gnc_dmy2timespec (int day, int month, int year)
-{
- return gnc_dmy2timespec_internal (day, month, year, TRUE);
-}
-
-Timespec
-gnc_dmy2timespec_end (int day, int month, int year)
-{
- return gnc_dmy2timespec_internal (day, month, year, FALSE);
-}
-
-/********************************************************************\
-\********************************************************************/
-
-long int
-gnc_timezone (struct tm *tm)
-{
- g_return_val_if_fail (tm != NULL, 0);
-
-#ifdef HAVE_STRUCT_TM_GMTOFF
- /* tm_gmtoff is seconds *east* of UTC and is
- * already adjusted for daylight savings time. */
- return -(tm->tm_gmtoff);
-#else
- /* timezone is seconds *west* of UTC and is
- * not adjusted for daylight savings time.
- * In Spring, we spring forward, wheee! */
- return timezone - (tm->tm_isdst > 0 ? 60 * 60 : 0);
-#endif
-}
-
-
-void
-timespecFromTime_t( Timespec *ts, time_t t )
-{
- ts->tv_sec = t;
- ts->tv_nsec = 0;
-}
-
-time_t
-timespecToTime_t (Timespec ts)
-{
- return ts.tv_sec;
-}
-
-void
-gnc_tm_get_day_start (struct tm *tm, time_t time_val)
-{
- /* Get the equivalent time structure */
- tm = localtime_r(&time_val, tm);
- gnc_tm_set_day_start(tm);
-}
-
-void
-gnc_tm_get_day_end (struct tm *tm, time_t time_val)
-{
- /* Get the equivalent time structure */
- tm = localtime_r(&time_val, tm);
- gnc_tm_set_day_end(tm);
-}
-
-time_t
-gnc_timet_get_day_start (time_t time_val)
-{
- struct tm tm;
-
- gnc_tm_get_day_start(&tm, time_val);
- return mktime(&tm);
-}
-
-time_t
-gnc_timet_get_day_end (time_t time_val)
-{
- struct tm tm;
-
- gnc_tm_get_day_end(&tm, time_val);
- return mktime(&tm);
-}
-
-
-#ifndef GNUCASH_MAJOR_VERSION
-time_t
-gnc_timet_get_day_start_gdate (GDate *date)
-{
- struct tm stm;
- time_t secs;
-
- stm.tm_year = g_date_year (date) - 1900;
- stm.tm_mon = g_date_month (date) - 1;
- stm.tm_mday = g_date_day (date);
- gnc_tm_set_day_start(&stm);
-
- /* Compute number of seconds */
- secs = mktime (&stm);
- return secs;
-}
-
-time_t
-gnc_timet_get_day_end_gdate (GDate *date)
-{
- struct tm stm;
- time_t secs;
-
- stm.tm_year = g_date_year (date) - 1900;
- stm.tm_mon = g_date_month (date) - 1;
- stm.tm_mday = g_date_day (date);
- gnc_tm_set_day_end(&stm);
-
- /* Compute number of seconds */
- secs = mktime (&stm);
- return secs;
-}
-#endif /* GNUCASH_MAJOR_VERSION */
-
-/* ======================================================== */
-
-void
-gnc_tm_get_today_start (struct tm *tm)
-{
- gnc_tm_get_day_start(tm, time(NULL));
-}
-
-void
-gnc_tm_get_today_end (struct tm *tm)
-{
- gnc_tm_get_day_end(tm, time(NULL));
-}
-
-time_t
-gnc_timet_get_today_start (void)
-{
- struct tm tm;
-
- gnc_tm_get_day_start(&tm, time(NULL));
- return mktime(&tm);
-}
-
-time_t
-gnc_timet_get_today_end (void)
-{
- struct tm tm;
-
- gnc_tm_get_day_end(&tm, time(NULL));
- return mktime(&tm);
-}
-
-/********************** END OF FILE *********************************\
-\********************************************************************/
Deleted: gnucash/trunk/src/engine/gnc-date.h
===================================================================
--- gnucash/trunk/src/engine/gnc-date.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/gnc-date.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,539 +0,0 @@
-/********************************************************************\
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
-\********************************************************************/
-/** @addtogroup Date
- Utility functions to handle date and time (adjusting, getting
- the current date, printing the date and time, etc.)
-
- Overall, this file is quite a mess. Note, however, that other
- applications, besides just GnuCash, use this file. In particular,
- GnoTime (gttr.sourcefore.net) uses this file, and this file is
- formally a part of QOF (qof.sourceforge.net).
-
- An important note about time-keeping: The general goal of any
- program that works with numeric time values SHOULD BE to always
- stores and use UNIVERSAL TIME internally. Universal time is the
- 'one true time' that is independent of one's location on planet
- Earth. It is measured in seconds from midnight January 1, 1970
- in localtime-Grenwich (GMT). If one wants to display the local
- time, then the display-print routine should make all final
- tweaks to print the local time. The local time *must not* be
- kept as a numeric value anywhere in the program. If one wants
- to parse a user's input string as if it were local time, then
- the output of the parse routine MUST BE universal time.
- A sane program must never ever store (to file or db) a time
- that is not Universal Time. Break these rules, and you will
- rue the day...
-
- \warning HACK ALERT -- the scan and print routines should probably be moved
- to somewhere else. The engine really isn't involved with things
- like printing formats. This is needed mostly by the GUI and so on.
- If a file-io backend needs date handling, it should do it itself,
- instead of depending on the routines here.
-
- @author Copyright (C) 1997 Robin D. Clark <rclark at cs.hmc.edu>
- @author Copyright (C) 1998-2001,2003 Linas Vepstas <linas at linas.org>
-*/
-
-/* @{
- @file gnc-date.h
- @brief Date and Time handling routines
-*/
-
-#ifndef GNC_DATE_H
-#define GNC_DATE_H
-
-#include <glib.h>
-#include <time.h>
-
-/** The maximum length of a string created by the date printers */
-#define MAX_DATE_LENGTH 31
-
-/** Constants *******************************************************/
-/** \brief UTC date format string.
-
-Timezone independent, date and time inclusive, as used in the QSF backend.
-The T and Z characters are from xsd:dateTime format in coordinated universal time, UTC.
-You can reproduce the string from the GNU/Linux command line using the date utility:
-date -u +%Y-%m-%dT%H:M:SZ = 2004-12-12T23:39:11Z The datestring must be timezone independent
-and include all specified fields. Remember to use gmtime() NOT localtime()!
-*/
-
-#define QOF_UTC_DATE_FORMAT "%Y-%m-%dT%H:%M:%SZ"
-
-/** Enum for determining a date format */
-typedef enum
-{
- QOF_DATE_FORMAT_US, /**< United states: mm/dd/yyyy */
- QOF_DATE_FORMAT_UK, /**< Britain: dd/mm/yyyy */
- QOF_DATE_FORMAT_CE, /**< Continental Europe: dd.mm.yyyy */
- QOF_DATE_FORMAT_ISO, /**< ISO: yyyy-mm-dd */
- QOF_DATE_FORMAT_UTC, /**< UTC: 2004-12-12T23:39:11Z */
- QOF_DATE_FORMAT_LOCALE, /**< Take from locale information */
- QOF_DATE_FORMAT_CUSTOM /**< Used by the check printing code */
-} QofDateFormat;
-
-#define DATE_FORMAT_FIRST QOF_DATE_FORMAT_US
-#define DATE_FORMAT_LAST QOF_DATE_FORMAT_LOCALE
-
-
-/**
- * This is how to format the month, as a number, an abbreviated string,
- * or the full name.
- */
-typedef enum {
- GNCDATE_MONTH_NUMBER,
- GNCDATE_MONTH_ABBREV,
- GNCDATE_MONTH_NAME
-} GNCDateMonthFormat;
-
-
-/** \name String / DateFormat conversion. */
-//@{
-
-/** \brief The string->value versions return FALSE on success and TRUE on failure */
-const char* gnc_date_dateformat_to_string(QofDateFormat format);
-
-/** \brief Converts the date format to a printable string.
-
-Note the reversed return values!
- at return FALSE on success, TRUE on failure.
-*/
-gboolean gnc_date_string_to_dateformat(const char* format_string,
- QofDateFormat *format);
-
-const char* gnc_date_monthformat_to_string(GNCDateMonthFormat format);
-
-/** \brief Converts the month format to a printable string.
-
-Note the reversed return values!
- at return FALSE on success, TRUE on failure.
-*/
-gboolean gnc_date_string_to_monthformat(const char *format_string,
- GNCDateMonthFormat *format);
-// @}
-
-/* Datatypes *******************************************************/
-
-/** \brief Use a 64-bit signed int timespec
- *
- * struct timespec64 is just like the unix 'struct timespec' except
- * that we use a 64-bit
- * signed int to store the seconds. This should adequately cover
- * dates in the distant future as well as the distant past, as long as
- * they're not more than a couple dozen times the age of the universe.
- * Note that both gcc and the IBM Toronto xlC compiler (aka CSet,
- * VisualAge, etc) correctly handle long long as a 64 bit quantity,
- * even on the 32-bit Intel x86 and PowerPC architectures. I'm
- * assuming that all the other modern compilers are clean on this
- * issue too. */
-
-#ifndef SWIG /* swig 1.1p5 can't hack the long long type */
-struct timespec64
-{
- long long int tv_sec;
- long int tv_nsec;
-};
-#endif /* SWIG */
-
-/** The Timespec is just like the unix 'struct timespec'
- * except that we use a 64-bit signed int to
- * store the seconds. This should adequately cover dates in the
- * distant future as well as the distant past, as long as they're not
- * more than a couple dozen times the age of the universe. Note that
- * both gcc and the IBM Toronto xlC compiler (aka CSet, VisualAge,
- * etc) correctly handle long long as a 64 bit quantity, even on the
- * 32-bit Intel x86 and PowerPC architectures. I'm assuming that all
- * the other modern compilers are clean on this issue too. */
-typedef struct timespec64 Timespec;
-
-
-/* Prototypes ******************************************************/
-
-/** \name Timespec functions */
-// @{
-/** strict equality */
-gboolean timespec_equal(const Timespec *ta, const Timespec *tb);
-
-/** comparison: if (ta < tb) -1; else if (ta > tb) 1; else 0; */
-int timespec_cmp(const Timespec *ta, const Timespec *tb);
-
-/** difference between ta and tb, results are normalised
- * ie tv_sec and tv_nsec of the result have the same size
- * abs(result.tv_nsec) <= 1000000000 */
-Timespec timespec_diff(const Timespec *ta, const Timespec *tb);
-
-/** absolute value, also normalised */
-Timespec timespec_abs(const Timespec *t);
-
-/** convert a timepair on a certain day (localtime) to
- * the timepair representing midday on that day */
-Timespec timespecCanonicalDayTime(Timespec t);
-
-/** Turns a time_t into a Timespec */
-void timespecFromTime_t( Timespec *ts, time_t t );
-
-/** Turns a Timespec into a time_t */
-time_t timespecToTime_t (Timespec ts);
-
-/** Convert a day, month, and year to a Timespec */
-Timespec gnc_dmy2timespec (int day, int month, int year);
-
-/** Same as gnc_dmy2timespec, but last second of the day */
-Timespec gnc_dmy2timespec_end (int day, int month, int year);
-
-/** The gnc_iso8601_to_timespec_gmt() routine converts an ISO-8601 style
- * date/time string to Timespec. Please note that ISO-8601 strings
- * are a representation of Universal Time (UTC), and as such, they
- * 'store' UTC. To make them human readable, they show timezone
- * information along with a local-time string. But fundamentally,
- * they *are* UTC. Thus, thir routine takes a UTC input, and
- * returns a UTC output.
- *
- * For example: 1998-07-17 11:00:00.68-0500
- * is 680 milliseconds after 11 o'clock, central daylight time
- * It is also 680 millisecs after 16:00:00 hours UTC.
- * \return The universl time.
- *
- * XXX Caution: this routine does not handle strings that specify
- * times before January 1 1970.
- */
-Timespec gnc_iso8601_to_timespec_gmt(const char *);
-
-/** The gnc_timespec_to_iso8601_buff() routine takes the input
- * UTC Timespec value and prints it as an ISO-8601 style string.
- * The buffer must be long enough to contain the NULL-terminated
- * string (32 characters + NUL). This routine returns a pointer
- * to the null terminator (and can thus be used in the 'stpcpy'
- * metaphor of string concatenation).
- *
- * Please note that ISO-8601 strings are a representation of
- * Universal Time (UTC), and as such, they 'store' UTC. To make them
- * human readable, they show timezone information along with a
- * local-time string. But fundamentally, they *are* UTC. Thus,
- * this routine takes a UTC input, and returns a UTC output.
- *
- * The string generated by this routine uses the local timezone
- * on the machine on which it is executing to create the timestring.
- */
-char * gnc_timespec_to_iso8601_buff (Timespec ts, char * buff);
-
-/** DOCUMENT ME! FIXME: Probably similar to xaccDMYToSec() this date
- * routine might return incorrect values for dates before 1970. */
-void gnc_timespec2dmy (Timespec ts, int *day, int *month, int *year);
-
-/** Add a number of months to a time value and normalize. Optionally
- * also track the last day of the month, i.e. 1/31 -> 2/28 -> 3/30. */
-void date_add_months (struct tm *tm, int months, gboolean track_last_day);
-
-/** \warning hack alert XXX FIXME -- these date routines return incorrect
- * values for dates before 1970. Most of them are good only up
- * till 2038. This needs fixing ...
- *
- * XXX This routine should be modified to assume that the
- * the user wanted the time at noon, localtime. The returned
- * time_t should be seconds (at GMT) of the local noon-time.
-*/
-time_t xaccDMYToSec (int day, int month, int year);
-
-/** The gnc_timezone function returns the number of seconds *west*
- * of UTC represented by the tm argument, adjusted for daylight
- * savings time.
- *
- * This function requires a tm argument returned by localtime or set
- * by mktime. This is a strange function! It requires that localtime
- * or mktime be called before use. Subsequent calls to localtime or
- * mktime *may* invalidate the result! The actual contents of tm *may*
- * be used for both timezone offset and daylight savings time, or only
- * daylight savings time! Timezone stuff under unix is not
- * standardized and is a big mess.
- */
-long int gnc_timezone (struct tm *tm);
-// @}
-
-/* ------------------------------------------------------------------------ */
-/** \name QofDateFormat functions */
-// @{
-/** The qof_date_format_get routine returns the date format that
- * the date printing will use when printing a date, and the scaning
- * routines will assume when parsing a date.
- * @returns: the one of the enumerated date formats.
- */
-QofDateFormat qof_date_format_get(void);
-
-/**
- * The qof_date_format_set() routine sets date format to one of
- * US, UK, CE, OR ISO. Checks to make sure it's a legal value.
- * Args: QofDateFormat: enumeration indicating preferred format
- */
-void qof_date_format_set(QofDateFormat df);
-
-/** This function returns a strftime formatting string for printing an
- * all numeric date (e.g. 2005-09-14). The string returned is based
- * upon the location specified.
- *
- * @param df The date style (us, uk, iso, etc) that should be provided.
- *
- * @return A formatting string that will print a date in the
- * requested style */
-const gchar *qof_date_format_get_string(QofDateFormat df);
-
-/** This function returns a strftime formatting string for printing a
- * date using words and numbers (e.g. 2005-September-14). The string
- * returned is based upon the location specified.
- *
- * @param df The date style (us, uk, iso, etc) that should be provided.
- *
- * @return A formatting string that will print a date in the
- * requested style */
-const gchar *qof_date_text_format_get_string(QofDateFormat df);
-// @}
-
-/** dateSeparator
- * Return the field separator for the current date format
- *
- * Args: none
- *
- * Return: date character
- *
- * Globals: global dateFormat value
- */
-char dateSeparator(void);
-
-/** \name Date Printing/Scanning functions
- */
-// @{
-/**
- * \warning HACK ALERT -- the scan and print routines should probably
- * be moved to somewhere else. The engine really isn't involved with
- * things like printing formats. This is needed mostly by the GUI and
- * so on. If a file-io thing needs date handling, it should do it
- * itself, instead of depending on the routines here.
- */
-
-/** qof_print_date_dmy_buff
- * Convert a date as day / month / year integers into a localized string
- * representation
- *
- * Args: buff - pointer to previously allocated character array; its size
- * must be at lease MAX_DATE_LENTH bytes.
- * len - length of the buffer, in bytes.
- * day - day of the month as 1 ... 31
- * month - month of the year as 1 ... 12
- * year - year (4-digit)
- *
- * Returns: number of characters printed
- *
- * Globals: global dateFormat value
- **/
-size_t qof_print_date_dmy_buff (char * buff, size_t buflen, int day, int month, int year);
-
-/** Convenience: calls through to qof_print_date_dmy_buff(). **/
-size_t qof_print_date_buff (char * buff, size_t buflen, time_t secs);
-
-/** Convenience; calls through to qof_print_date_dmy_buff(). **/
-size_t qof_print_gdate( char *buf, size_t bufflen, GDate *gd );
-
-/** Convenience; calls through to qof_print_date_dmy_buff().
- * Return: string, which should be freed when no longer needed.
- * **/
-char * qof_print_date (time_t secs);
-
-/** Convenience; calls through to qof_print_date_dmy_buff().
- * Return: static global string.
- * \warning This routine is not thread-safe, because it uses a single
- * global buffer to store the return value. Use qof_print_date_buff()
- * or qof_print_date() instead.
- * **/
-const char * gnc_print_date(Timespec ts);
-
-/* ------------------------------------------------------------------ */
-/* time printing utilities */
-
-/** The qof_print_hours_elapsed_buff() routine will print the 'secs' argument
- * as HH:MM, and will print the seconds if show_secs is true.
- * Thus, for example, secs=3599 will print as 0:59
- * Returns the number of bytes copied.
- */
-size_t qof_print_hours_elapsed_buff (char * buff, size_t len, int secs, gboolean show_secs);
-size_t qof_print_minutes_elapsed_buff (char * buff, size_t len, int secs, gboolean show_secs);
-
-/** The qof_print_time_buff() routine prints only the hour-part of the date.
- * Thus, if secs is ...
- * Returns the number of bytes printed.
- */
-
-size_t qof_print_time_buff (char * buff, size_t len, time_t secs);
-size_t qof_print_date_time_buff (char * buff, size_t len, time_t secs);
-
-/** The qof_is_same_day() routine returns 0 if both times are in the
- * same day.
- */
-
-gboolean qof_is_same_day (time_t, time_t);
-
-/* ------------------------------------------------------------------ */
-/** The xaccDateUtilGetStamp() routine will take the given time in
- * seconds and return a buffer containing a textual for the date.
- * @param thyme The time in seconds to convert.
- * @return A pointer to the generated string.
- * @note The caller owns this buffer and must free it when done. */
-char * xaccDateUtilGetStamp (time_t thyme);
-
-/** qof_scan_date
- * Convert a string into day / month / year integers according to
- * the current dateFormat value.
- *
- * Args: buff - pointer to date string
- * day - will store day of the month as 1 ... 31
- * month - will store month of the year as 1 ... 12
- * year - will store the year (4-digit)
- *
- * Return: TRUE if the string seemed to be a valid date; else FALSE.
- *
- * Globals: uses global dateFormat value to assist in parsing.
- */
-gboolean qof_scan_date (const char *buff, int *day, int *month, int *year);
-
-/** as above, but returns seconds */
-gboolean qof_scan_date_secs (const char *buff, time_t *secs);
-
-// @}
-/** \name Date Start/End Adjustment routines
- * Given a time value, adjust it to be the beginning or end of that day.
- */
-// @{
-
-/** The gnc_tm_set_day_start() inline routine will set the appropriate
- * fields in the struct tm to indicate the first second of that day.
- * This routine assumes that the contents of the data structure is
- * already in normalized form. */
-static inline
-void gnc_tm_set_day_start (struct tm *tm)
-{
- /* First second of the day */
- tm->tm_hour = 0;
- tm->tm_min = 0;
- tm->tm_sec = 0;
- tm->tm_isdst = -1;
-}
-
-/** The gnc_tm_set_day_start() inline routine will set the appropriate
- * fields in the struct tm to indicate noon of that day. This
- * routine assumes that the contents of the data structure is already
- * in normalized form.*/
-static inline
-void gnc_tm_set_day_middle (struct tm *tm)
-{
- /* First second of the day */
- tm->tm_hour = 12;
- tm->tm_min = 0;
- tm->tm_sec = 0;
- tm->tm_isdst = -1;
-}
-
-/** The gnc_tm_set_day_start() inline routine will set the appropriate
- * fields in the struct tm to indicate the last second of that day.
- * This routine assumes that the contents of the data structure is
- * already in normalized form.*/
-static inline
-void gnc_tm_set_day_end (struct tm *tm)
-{
- /* Last second of the day */
- tm->tm_hour = 23;
- tm->tm_min = 59;
- tm->tm_sec = 59;
- tm->tm_isdst = -1;
-}
-
-/** The gnc_tm_get_day_start() routine will convert the given time in
- * seconds to the struct tm format, and then adjust it to the
- * first second of that day. */
-void gnc_tm_get_day_start(struct tm *tm, time_t time_val);
-
-/** The gnc_tm_get_day_end() routine will convert the given time in
- * seconds to the struct tm format, and then adjust it to the
- * last second of that day. */
-void gnc_tm_get_day_end(struct tm *tm, time_t time_val);
-
-/** The gnc_timet_get_day_start() routine will take the given time in
- * seconds and adjust it to the last second of that day. */
-time_t gnc_timet_get_day_start(time_t time_val);
-
-/** The gnc_timet_get_day_end() routine will take the given time in
- * seconds and adjust it to the last second of that day. */
-time_t gnc_timet_get_day_end(time_t time_val);
-
-#ifndef GNUCASH_MAJOR_VERSION
-/** The gnc_timet_get_day_start() routine will take the given time in
- * GLib GDate format and adjust it to the last second of that day.
- *
- * @deprecated
- */
-time_t gnc_timet_get_day_start_gdate (GDate *date);
-
-/** The gnc_timet_get_day_end() routine will take the given time in
- * GLib GDate format and adjust it to the last second of that day.
- *
- * @deprecated
- */
-time_t gnc_timet_get_day_end_gdate (GDate *date);
-#endif /* GNUCASH_MAJOR_VERSION */
-
-/** Get the numerical last date of the month. (28, 29, 30, 31) */
-int date_get_last_mday(struct tm *tm);
-
-/** Is the mday field the last day of the specified month.*/
-gboolean date_is_last_mday(struct tm *tm);
-
-/** DOCUMENT ME! Probably the same as date_get_last_mday() */
-int gnc_date_my_last_mday (int month, int year);
-/** DOCUMENT ME! Probably the same as date_get_last_mday() */
-int gnc_timespec_last_mday (Timespec ts);
-// @}
-
-/* ======================================================== */
-
-/** \name Today's Date */
-// @{
-/** The gnc_tm_get_today_start() routine takes a pointer to a struct
- * tm and fills it in with the first second of the today. */
-void gnc_tm_get_today_start(struct tm *tm);
-
-/** The gnc_tm_get_today_end() routine takes a pointer to a struct
- * tm and fills it in with the last second of the today. */
-void gnc_tm_get_today_end(struct tm *tm);
-
-/** The gnc_timet_get_today_start() routine returns a time_t value
- * corresponding to the first second of today. */
-time_t gnc_timet_get_today_start(void);
-
-/** The gnc_timet_get_today_end() routine returns a time_t value
- * corresponding to the last second of today. */
-time_t gnc_timet_get_today_end(void);
-
-/** The xaccDateUtilGetStampNow() routine returns the current time in
- * seconds in textual format.
- * @return A pointer to the generated string.
- * @note The caller owns this buffer and must free it when done. */
-char * xaccDateUtilGetStampNow (void);
-
-//@}
-//@}
-#endif /* GNC_DATE_H */
-
Deleted: gnucash/trunk/src/engine/gnc-engine-util.c
===================================================================
--- gnucash/trunk/src/engine/gnc-engine-util.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/gnc-engine-util.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,307 +0,0 @@
-/********************************************************************\
- * gnc-engine-util.c -- QOF utility functions *
- * Copyright (C) 1997 Robin D. Clark *
- * Copyright (C) 1997-2001,2004 Linas Vepstas <linas at linas.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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
- * Author: Rob Clark (rclark at cs.hmc.edu) *
- * Author: Linas Vepstas (linas at linas.org) *
-\********************************************************************/
-
-#include "config.h"
-
-#include <ctype.h>
-#include <glib.h>
-#include <stdlib.h>
-#include <string.h>
-#include "qof.h"
-#include "gnc-engine-util.h"
-
-
-/********************************************************************\
-\********************************************************************/
-
-/* Search for str2 in first nchar chars of str1, ignore case.. Return
- * pointer to first match, or null. */
-char *
-strncasestr(const char *str1, const char *str2, size_t len)
-{
- while (*str1 && len--)
- {
- if (toupper(*str1) == toupper(*str2))
- {
- if (strncasecmp(str1,str2,strlen(str2)) == 0)
- {
- return (char *) str1;
- }
- }
- str1++;
- }
- return NULL;
-}
-
-/* Search for str2 in str1, ignore case. Return pointer to first
- * match, or null. */
-char *
-strcasestr(const char *str1, const char *str2)
-{
- size_t len = strlen (str1);
- char * retval = strncasestr (str1, str2, len);
- return retval;
-}
-
-/********************************************************************\
-\********************************************************************/
-
-int
-safe_strcmp (const char * da, const char * db)
-{
- SAFE_STRCMP (da, db);
- return 0;
-}
-
-int
-safe_strcasecmp (const char * da, const char * db)
-{
- SAFE_STRCASECMP (da, db);
- return 0;
-}
-
-int
-null_strcmp (const char * da, const char * db)
-{
- if (da && db) return strcmp (da, db);
- if (!da && db && 0==db[0]) return 0;
- if (!db && da && 0==da[0]) return 0;
- if (!da && db) return -1;
- if (da && !db) return +1;
- return 0;
-}
-
-/********************************************************************\
-\********************************************************************/
-
-#define MAX_DIGITS 50
-
-/* inverse of strtoul */
-char *
-ultostr (unsigned long val, int base)
-{
- char buf[MAX_DIGITS];
- unsigned long broke[MAX_DIGITS];
- int i;
- unsigned long places=0, reval;
-
- if ((2>base) || (36<base)) return NULL;
-
- /* count digits */
- places = 0;
- for (i=0; i<MAX_DIGITS; i++) {
- broke[i] = val;
- places ++;
- val /= base;
- if (0 == val) break;
- }
-
- /* normalize */
- reval = 0;
- for (i=places-2; i>=0; i--) {
- reval += broke[i+1];
- reval *= base;
- broke[i] -= reval;
- }
-
- /* print */
- for (i=0; i<(int)places; i++) {
- if (10>broke[i]) {
- buf[places-1-i] = 0x30+broke[i]; /* ascii digit zero */
- } else {
- buf[places-1-i] = 0x41-10+broke[i]; /* ascii capital A */
- }
- }
- buf[places] = 0x0;
-
- return g_strdup (buf);
-}
-
-/********************************************************************\
- * returns TRUE if the string is a number, possibly with whitespace
-\********************************************************************/
-
-gboolean
-gnc_strisnum(const char *s)
-{
- if (s == NULL) return FALSE;
- if (*s == 0) return FALSE;
-
- while (*s && isspace(*s))
- s++;
-
- if (*s == 0) return FALSE;
- if (!isdigit(*s)) return FALSE;
-
- while (*s && isdigit(*s))
- s++;
-
- if (*s == 0) return TRUE;
-
- while (*s && isspace(*s))
- s++;
-
- if (*s == 0) return TRUE;
-
- return FALSE;
-}
-
-/********************************************************************\
- * our own version of stpcpy
-\********************************************************************/
-
-char *
-gnc_stpcpy (char *dest, const char *src)
-{
- strcpy (dest, src);
- return (dest + strlen (src));
-}
-
-/* =================================================================== */
-/* Return NULL if the field is whitespace (blank, tab, formfeed etc.)
- * Else return pointer to first non-whitespace character. */
-
-const char *
-qof_util_whitespace_filter (const char * val)
-{
- size_t len;
- if (!val) return NULL;
-
- len = strspn (val, "\a\b\t\n\v\f\r ");
- if (0 == val[len]) return NULL;
- return val+len;
-}
-
-/* =================================================================== */
-/* Return integer 1 if the string starts with 't' or 'T' or contains the
- * word 'true' or 'TRUE'; if string is a number, return that number. */
-
-int
-qof_util_bool_to_int (const char * val)
-{
- const char * p = qof_util_whitespace_filter (val);
- if (!p) return 0;
- if ('t' == p[0]) return 1;
- if ('T' == p[0]) return 1;
- if ('y' == p[0]) return 1;
- if ('Y' == p[0]) return 1;
- if (strstr (p, "true")) return 1;
- if (strstr (p, "TRUE")) return 1;
- if (strstr (p, "yes")) return 1;
- if (strstr (p, "YES")) return 1;
- return atoi (val);
-}
-
-/********************************************************************\
- * The engine string cache
-\********************************************************************/
-
-static GCache * gnc_string_cache = NULL;
-
-#ifdef THESE_CAN_BE_USEFUL_FOR_DEGUGGING
-static guint g_str_hash_KEY(gconstpointer v) {
- return g_str_hash(v);
-}
-static guint g_str_hash_VAL(gconstpointer v) {
- return g_str_hash(v);
-}
-static gpointer g_strdup_VAL(gpointer v) {
- return g_strdup(v);
-}
-static gpointer g_strdup_KEY(gpointer v) {
- return g_strdup(v);
-}
-static void g_free_VAL(gpointer v) {
- return g_free(v);
-}
-static void g_free_KEY(gpointer v) {
- return g_free(v);
-}
-static gboolean gnc_str_equal(gconstpointer v, gconstpointer v2)
-{
- return (v && v2) ? g_str_equal(v, v2) : FALSE;
-}
-#endif
-
-GCache*
-gnc_engine_get_string_cache(void)
-{
- if(!gnc_string_cache) {
- gnc_string_cache = g_cache_new(
- (GCacheNewFunc) g_strdup, /* value_new_func */
- g_free, /* value_destroy_func */
- (GCacheDupFunc) g_strdup, /* key_dup_func */
- g_free, /* key_destroy_func */
- g_str_hash, /* hash_key_func */
- g_str_hash, /* hash_value_func */
- g_str_equal); /* key_equal_func */
- }
- return gnc_string_cache;
-}
-
-void
-gnc_engine_string_cache_destroy (void)
-{
- if (gnc_string_cache)
- g_cache_destroy (gnc_string_cache);
- gnc_string_cache = NULL;
-}
-
-void
-gnc_string_cache_remove(gconstpointer key)
-{
- g_cache_remove(gnc_engine_get_string_cache(), key);
-}
-
-
-gpointer
-gnc_string_cache_insert(gpointer key)
-{
- return g_cache_insert(gnc_engine_get_string_cache(), key);
-}
-
-void
-qof_init (void)
-{
- gnc_engine_get_string_cache ();
- guid_init ();
- qof_object_initialize ();
- qof_query_init ();
- qof_book_register ();
-}
-
-void
-qof_close(void)
-{
- qof_query_shutdown ();
- qof_object_shutdown ();
- guid_shutdown ();
- gnc_engine_string_cache_destroy ();
-}
-
-
-/************************* END OF FILE ******************************\
-\********************************************************************/
Deleted: gnucash/trunk/src/engine/gnc-engine-util.h
===================================================================
--- gnucash/trunk/src/engine/gnc-engine-util.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/gnc-engine-util.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,264 +0,0 @@
-/********************************************************************\
- * gnc-engine-util.h -- QOF utility functions *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
-\********************************************************************/
-
-/** @addtogroup Utilities
- @{ */
-/** @file gnc-engine-util.h
- @brief QOF utility functions
- @author Copyright (C) 1997 Robin D. Clark <rclark at cs.hmc.edu>
- @author Copyright (C) 2000 Bill Gribble <grib at billgribble.com>
- @author Copyright (C) 1997-2002,2004 Linas Vepstas <linas at linas.org>
-*/
-
-#ifndef QOF_UTIL_H
-#define QOF_UTIL_H
-
-#include <glib.h>
-#include <stddef.h>
-#include "config.h"
-#include "qof.h"
-
-/** Macros *****************************************************/
-
-/* CAS: Notice that this macro does nothing if pointer args are equal.
- Otherwise, it returns an integer. Actually, perhaps these macro
- should be private. They are NOT good substitutes for the function
- versions like safe_strcmp(). Maybe external users of these 3
- macros should be converted to use safe_strcmp(). Actually, THESE
- MACROS AFFECT CONTROL FLOW. YUCK! */
-#define SAFE_STRCMP_REAL(fcn,da,db) { \
- if ((da) && (db)) { \
- if ((da) != (db)) { \
- int retval = fcn ((da), (db)); \
- /* if strings differ, return */ \
- if (retval) return retval; \
- } \
- } else \
- if ((!(da)) && (db)) { \
- return -1; \
- } else \
- if ((da) && (!(db))) { \
- return +1; \
- } \
-}
-
-#define SAFE_STRCMP(da,db) SAFE_STRCMP_REAL(strcmp,(da),(db))
-#define SAFE_STRCASECMP(da,db) SAFE_STRCMP_REAL(strcasecmp,(da),(db))
-
-/** \name typedef enum as string macros
-@{
-*/
-#define ENUM_BODY(name, value) \
- name value,
-
-#define AS_STRING_CASE(name, value) \
- case name: { return #name; }
-
-#define FROM_STRING_CASE(name, value) \
- if (strcmp(str, #name) == 0) { \
- return name; }
-
-#define DEFINE_ENUM(name, list) \
- typedef enum { \
- list(ENUM_BODY) \
- }name;
-
-#define AS_STRING_DEC(name, list) \
- const char* name##asString(name n);
-
-#define AS_STRING_FUNC(name, list) \
- const char* name##asString(name n) { \
- switch (n) { \
- list(AS_STRING_CASE) \
- default: return ""; } }
-
-#define FROM_STRING_DEC(name, list) \
- name name##fromString \
- (const char* str);
-
-#define FROM_STRING_FUNC(name, list) \
- name name##fromString \
- (const char* str) { \
- if(str == NULL) { return 0; } \
- list(FROM_STRING_CASE) \
- return 0; }
-
-/** @} */
-
-/** \name enum as string with no typedef
-@{
-
- Similar but used when the enum is NOT a typedef
- note the LACK of a define_enum macro - don't use one!
-
- ENUM_BODY is used in both types.
- */
-
-#define FROM_STRING_DEC_NON_TYPEDEF(name, list) \
- void name##fromString \
- (const char* str, enum name *type);
-
-#define FROM_STRING_CASE_NON_TYPEDEF(name, value) \
- if (strcmp(str, #name) == 0) { *type = name; }
-
-#define FROM_STRING_FUNC_NON_TYPEDEF(name, list) \
- void name##fromString \
- (const char* str, enum name *type) { \
- if(str == NULL) { return; } \
- list(FROM_STRING_CASE_NON_TYPEDEF) }
-
-#define AS_STRING_DEC_NON_TYPEDEF(name, list) \
- const char* name##asString(enum name n);
-
-#define AS_STRING_FUNC_NON_TYPEDEF(name, list) \
- const char* name##asString(enum name n) { \
- switch (n) { \
- list(AS_STRING_CASE_NON_TYPEDEF) \
- default: return ""; } }
-
-#define AS_STRING_CASE_NON_TYPEDEF(name, value) \
- case name: { return #name; }
-
-/** @} */
-
-/* Define the long long int conversion for scanf */
-#if HAVE_SCANF_LLD
-# define GNC_SCANF_LLD "%lld"
-#else
-# define GNC_SCANF_LLD "%qd"
-#endif
-
-/** @name Convenience wrappers
- @{
-*/
-
-/** \brief Initialise the Query Object Framework
-
-Used for non-Guile applications or test routines.
-*/
-void qof_init (void);
-
-/** \brief Safely close down the Query Object Framework
-
-Used for non-Guile applications or test routines.
-*/
-void qof_close (void);
-
-/** @} */
-
-/** Prototypes *************************************************/
-
-/** The safe_strcmp compares strings a and b the same way that strcmp()
- * does, except that either may be null. This routine assumes that
- * a non-null string is always greater than a null string.
- */
-int safe_strcmp (const char * da, const char * db);
-int safe_strcasecmp (const char * da, const char * db);
-
-/** The null_strcmp compares strings a and b the same way that strcmp()
- * does, except that either may be null. This routine assumes that
- * a null string is equal to the empty string.
- */
-int null_strcmp (const char * da, const char * db);
-
-/** Search for str2 in first nchar chars of str1, ignore case. Return
- * pointer to first match, or null. These are just like that strnstr
- * and the strstr functions, except that they ignore the case. */
-extern char *strncasestr(const char *str1, const char *str2, size_t len);
-extern char *strcasestr(const char *str1, const char *str2);
-
-/** The ultostr() subroutine is the inverse of strtoul(). It accepts a
- * number and prints it in the indicated base. The returned string
- * should be g_freed when done. */
-char * ultostr (unsigned long val, int base);
-
-/** Returns true if string s is a number, possibly surrounded by
- * whitespace. */
-gboolean gnc_strisnum(const char *s);
-
-/** Local copy of stpcpy, used wtih libc's that don't have one. */
-char * gnc_stpcpy (char *dest, const char *src);
-
-#ifndef HAVE_STPCPY
-#define stpcpy gnc_stpcpy
-#endif
-
-/** Return NULL if the field is whitespace (blank, tab, formfeed etc.)
- * Else return pointer to first non-whitespace character.
- */
-const char * qof_util_whitespace_filter (const char * val);
-
-/** Return integer 1 if the string starts with 't' or 'T' or
- * contains the word 'true' or 'TRUE'; if string is a number,
- * return that number. (Leading whitespace is ignored). */
-int qof_util_bool_to_int (const char * val);
-
-
-/** Gnucash's String Cache:
- *
- * Many strings used throughout the engine are likely to be duplicated.
- * So we provide a reference counted cache system for the strings, which
- * shares strings whenever possible.
- *
- * Use gnc_string_cache_insert to insert a string into the cache (it
- * will return a pointer to the cached string). Basically you should
- * use this instead of g_strdup.
- *
- * Use gnc_string_cache_remove (giving it a pointer to a cached
- * string) if the string is unused. If this is the last reference to
- * the string it will be removed from the cache, otherwise it will
- * just decrement the reference count. Basically you should use this
- * instead of g_free.
- *
- * Just in case it's not clear: The remove function must NOT be called
- * for the string you passed INTO the insert function. It must be
- * called for the _cached_ string that is _returned_ by the insert
- * function.
- *
- * Note that all the work is done when inserting or removing. Once
- * cached the strings are just plain C strings.
- *
- * The string cache is demand-created on first use.
- *
- **/
-
-/** \deprecated use qof_init instead.
-
-Get the gnc_string_cache. Create it if it doesn't exist already
-*/
-GCache* gnc_engine_get_string_cache(void);
-
-/** Destroy the gnc_string_cache */
-void gnc_engine_string_cache_destroy (void);
-
-/* You can use this function as a destroy notifier for a GHashTable
- that uses common strings as keys (or values, for that matter.) */
-void gnc_string_cache_remove(gconstpointer key);
-
-/* You can use this function with g_hash_table_insert(), or the key
- (or value), as long as you use the destroy notifier above. */
-gpointer gnc_string_cache_insert(gpointer key);
-
-#define CACHE_INSERT(str) gnc_string_cache_insert((gpointer)(str));
-#define CACHE_REMOVE(str) gnc_string_cache_remove((str));
-
-#endif /* QOF_UTIL_H */
-/** @} */
Deleted: gnucash/trunk/src/engine/gnc-event-p.h
===================================================================
--- gnucash/trunk/src/engine/gnc-event-p.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/gnc-event-p.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,37 +0,0 @@
-/********************************************************************
- * gnc-event-p.h -- private engine event handling interface *
- * Copyright 2000 Dave Peticolas <dave at krondo.com> *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
- ********************************************************************/
-
-#ifndef GNC_EVENT_P_H
-#define GNC_EVENT_P_H
-
-#include "gnc-event.h"
-#include "qofid.h"
-
-/* XXX deprecated, but still usedion on postgres backend */
-void gnc_engine_generate_event (const GUID *, QofIdType, GNCEngineEventType);
-
-/* generates an event even when events are suspended! */
-void gnc_engine_force_event (QofEntity *entity,
- GNCEngineEventType event_type);
-
-#endif
Deleted: gnucash/trunk/src/engine/gnc-event.c
===================================================================
--- gnucash/trunk/src/engine/gnc-event.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/gnc-event.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,224 +0,0 @@
-/********************************************************************
- * gnc-event.c -- engine event handling implementation *
- * Copyright 2000 Dave Peticolas <dave at krondo.com> *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
- ********************************************************************/
-
-#include "config.h"
-
-#include "gnc-event-p.h"
-#include "gnc-trace.h"
-
-
-/** Declarations ****************************************************/
-
-typedef struct
-{
- GNCEngineEventHandler handler;
- gpointer user_data;
-
- gint handler_id;
-} HandlerInfo;
-
-
-/** Static Variables ************************************************/
-static guint suspend_counter = 0;
-static gint next_handler_id = 1;
-static GList *handlers = NULL;
-
-/* This static indicates the debugging module that this .o belongs to. */
-static QofLogModule log_module = QOF_MOD_ENGINE;
-
-
-/** Implementations *************************************************/
-
-gint
-gnc_engine_register_event_handler (GNCEngineEventHandler handler,
- gpointer user_data)
-{
- HandlerInfo *hi;
- gint handler_id;
- GList *node;
-
- ENTER ("(handler=%p, data=%p)", handler, user_data);
- /* sanity check */
- if (!handler)
- {
- PERR ("no handler specified");
- return 0;
- }
-
- /* look for a free handler id */
- handler_id = next_handler_id;
- node = handlers;
-
- while (node)
- {
- hi = node->data;
-
- if (hi->handler_id == handler_id)
- {
- handler_id++;
- node = handlers;
- continue;
- }
-
- node = node->next;
- }
-
- /* Found one, add the handler */
- hi = g_new0 (HandlerInfo, 1);
-
- hi->handler = handler;
- hi->user_data = user_data;
- hi->handler_id = handler_id;
-
- handlers = g_list_prepend (handlers, hi);
-
- /* Update id for next registration */
- next_handler_id = handler_id + 1;
-
- LEAVE ("(handler=%p, data=%p) handler_id=%d", handler, user_data, handler_id);
- return handler_id;
-}
-
-void
-gnc_engine_unregister_event_handler (gint handler_id)
-{
- GList *node;
-
- ENTER ("(handler_id=%d)", handler_id);
- for (node = handlers; node; node = node->next)
- {
- HandlerInfo *hi = node->data;
-
- if (hi->handler_id != handler_id)
- continue;
-
- /* Found it, take out of list */
- handlers = g_list_remove_link (handlers, node);
-
- LEAVE ("(handler_id=%d) handler=%p data=%p", handler_id, hi->handler, hi->user_data);
- /* safety */
- hi->handler = NULL;
-
- g_list_free_1 (node);
- g_free (hi);
-
- return;
- }
-
- PERR ("no such handler: %d", handler_id);
-}
-
-void
-gnc_engine_suspend_events (void)
-{
- suspend_counter++;
-
- if (suspend_counter == 0)
- {
- PERR ("suspend counter overflow");
- }
-}
-
-void
-gnc_engine_resume_events (void)
-{
- if (suspend_counter == 0)
- {
- PERR ("suspend counter underflow");
- return;
- }
-
- suspend_counter--;
-}
-
-static void
-gnc_engine_generate_event_internal (QofEntity *entity,
- GNCEngineEventType event_type)
-{
- GList *node;
- GList *next_node = NULL;
-
- g_return_if_fail(entity);
-
- switch (event_type)
- {
- case GNC_EVENT_NONE:
- return;
-
- case GNC_EVENT_CREATE:
- case GNC_EVENT_MODIFY:
- case GNC_EVENT_DESTROY:
- case GNC_EVENT_ADD:
- case GNC_EVENT_REMOVE:
- break;
-
- default:
- PERR ("bad event type %d", event_type);
- return;
- }
-
- for (node = handlers; node; node = next_node)
- {
- HandlerInfo *hi = node->data;
-
- next_node = node->next;
- PINFO ("id=%d hi=%p han=%p", hi->handler_id, hi, hi->handler);
- if (hi->handler)
- hi->handler ((GUID *)&entity->guid, entity->e_type, event_type, hi->user_data);
- }
-}
-
-void
-gnc_engine_force_event (QofEntity *entity,
- GNCEngineEventType event_type)
-{
- if (!entity)
- return;
-
- gnc_engine_generate_event_internal (entity, event_type);
-}
-
-void
-gnc_engine_gen_event (QofEntity *entity, GNCEngineEventType event_type)
-{
- if (!entity)
- return;
-
- if (suspend_counter)
- return;
-
- gnc_engine_generate_event_internal (entity, event_type);
-}
-
-void
-gnc_engine_generate_event (const GUID *guid, QofIdType e_type,
- GNCEngineEventType event_type)
-{
- QofEntity ent;
- ent.guid = *guid;
- ent.e_type = e_type;
- if (suspend_counter) return;
- gnc_engine_generate_event_internal (&ent, event_type);
-}
-
-/* =========================== END OF FILE ======================= */
Deleted: gnucash/trunk/src/engine/gnc-event.h
===================================================================
--- gnucash/trunk/src/engine/gnc-event.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/gnc-event.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,118 +0,0 @@
-/********************************************************************
- * gnc-event.h -- engine event handling interface *
- * Copyright 2000 Dave Peticolas <dave at krondo.com> *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
- ********************************************************************/
-
-/** @addtogroup Event
-@{
-*/
-/** @file gnc-event.h
- @brief engine event handling interface
- @author Copyright 2000 Dave Peticolas <dave at krondo.com>
-*/
-
-#ifndef GNC_EVENT_H
-#define GNC_EVENT_H
-
-#include <glib.h>
-
-#include "guid.h"
-#include "qofid.h"
-
-typedef enum
-{
- GNC_EVENT_NONE = 0,
- GNC_EVENT_CREATE = 1 << 0,
- GNC_EVENT_MODIFY = 1 << 1,
- GNC_EVENT_DESTROY = 1 << 2,
- GNC_EVENT_ADD = 1 << 3,
- GNC_EVENT_REMOVE = 1 << 4,
- GNC_EVENT_ALL = 0xff
-} GNCEngineEventType;
-
-
-/** GNCEngineEventHandler
-
- * Handler invoked when an engine event occurs.
- *
- * @param entity: GUID of entity generating event
- * @param type: QofIdType of the entity generating the event
- * @param event_type: one of the single-bit GNCEngineEventTypes, not a combination
- * @param user_data: user_data supplied when handler was registered.
- */
-typedef void (*GNCEngineEventHandler) (GUID *entity, QofIdType type,
- GNCEngineEventType event_type,
- gpointer user_data);
-
-/** gnc_engine_register_event_handler
-
- * Register a handler for engine events.
- *
- * @param handler: handler to register
- * @param user_data: data provided when handler is invoked
- *
- * @return id identifying handler
- */
-gint gnc_engine_register_event_handler (GNCEngineEventHandler handler,
- gpointer user_data);
-
-/** gnc_engine_unregister_event_handler
-
- * Unregister an engine event handler.
- *
- * @param handler_id: the id of the handler to unregister
- */
-void gnc_engine_unregister_event_handler (gint handler_id);
-
-/** gnc_engine_generate_event
-
- * Invoke all registered event handlers using the given arguments.
- *
- * GNC_EVENT_CREATE events should be generated after the object
- * has been created and registered in the engine entity table.
- * GNC_EVENT_MODIFY events should be generated whenever any data
- * member or submember (i.e., splits) is changed.
- * GNC_EVENT_DESTROY events should be called before the object
- * has been destroyed or removed from the entity table.
- *
- * @param entity: the GUID of the entity generating the event
- * @param event_type: the type of event -- this should be one of the
- * single-bit GNCEngineEventType values, not a combination.
- */
-void gnc_engine_gen_event (QofEntity *entity,
- GNCEngineEventType event_type);
-/** gnc_engine_suspend_events
-
- * Suspend all engine events. This function may be
- * called multiple times. To resume event generation,
- * an equal number of calls to gnc_engine_resume_events
- * must be made.
- */
-void gnc_engine_suspend_events (void);
-
-/** gnc_engine_resume_events
-
- * Resume engine event generation.
- */
-void gnc_engine_resume_events (void);
-
-#endif
-/** @} */
Deleted: gnucash/trunk/src/engine/gnc-numeric.c
===================================================================
--- gnucash/trunk/src/engine/gnc-numeric.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/gnc-numeric.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,1306 +0,0 @@
-/********************************************************************
- * gnc-numeric.c -- an exact-number library for accounting use *
- * Copyright (C) 2000 Bill Gribble *
- * Copyright (C) 2004 Linas Vepstas <linas at linas.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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
- *******************************************************************/
-
-#define _GNU_SOURCE
-
-#include "config.h"
-
-#include <glib.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "gnc-numeric.h"
-#include "qofmath128.c"
-
-/* static short module = MOD_ENGINE; */
-
-/* =============================================================== */
-
-#if 0
-static const char * _numeric_error_strings[] =
-{
- "No error",
- "Argument is not a valid number",
- "Intermediate result overflow",
- "Argument denominators differ in GNC_HOW_DENOM_FIXED operation",
- "Remainder part in GNC_HOW_RND_NEVER operation"
-};
-#endif
-
-/* =============================================================== */
-/* This function is small, simple, and used everywhere below,
- * lets try to inline it.
- */
-inline GNCNumericErrorCode
-gnc_numeric_check(gnc_numeric in)
-{
- if(in.denom != 0)
- {
- return GNC_ERROR_OK;
- }
- else if(in.num)
- {
- if ((0 < in.num) || (-4 > in.num))
- {
- in.num = (gint64) GNC_ERROR_OVERFLOW;
- }
- return (GNCNumericErrorCode) in.num;
- }
- else
- {
- return GNC_ERROR_ARG;
- }
-}
-
-/**
- * Find the least common multiple of the denominators of a and b.
- */
-
-static inline gint64
-gnc_numeric_lcd(gnc_numeric a, gnc_numeric b)
-{
- qofint128 lcm;
- if(gnc_numeric_check(a) || gnc_numeric_check(b))
- {
- return GNC_ERROR_ARG;
- }
-
- if (b.denom == a.denom) return a.denom;
-
- /* Special case: smaller divides smoothly into larger */
- if ((b.denom < a.denom) && ((a.denom % b.denom) == 0))
- {
- return a.denom;
- }
- if ((a.denom < b.denom) && ((b.denom % a.denom) == 0))
- {
- return b.denom;
- }
-
- lcm = lcm128 (a.denom, b.denom);
- if (lcm.isbig) return GNC_ERROR_ARG;
- return lcm.lo;
-}
-
-
-/** Return the ratio n/d reduced so that there are no common factors. */
-static inline gnc_numeric
-reduce128(qofint128 n, gint64 d)
-{
- gint64 t;
- gint64 num;
- gint64 denom;
- gnc_numeric out;
- qofint128 red;
-
- t = rem128 (n, d);
- num = d;
- denom = t;
-
- /* The strategy is to use Euclid's algorithm */
- while (denom > 0)
- {
- t = num % denom;
- num = denom;
- denom = t;
- }
- /* num now holds the GCD (Greatest Common Divisor) */
-
- red = div128 (n, num);
- if (red.isbig)
- {
- return gnc_numeric_error (GNC_ERROR_OVERFLOW);
- }
- out.num = red.lo;
- if (red.isneg) out.num = -out.num;
- out.denom = d / num;
- return out;
-}
-
-/********************************************************************
- * gnc_numeric_zero_p
- ********************************************************************/
-
-gboolean
-gnc_numeric_zero_p(gnc_numeric a)
-{
- if(gnc_numeric_check(a))
- {
- return 0;
- }
- else
- {
- if((a.num == 0) && (a.denom != 0))
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
-}
-
-/********************************************************************
- * gnc_numeric_negative_p
- ********************************************************************/
-
-gboolean
-gnc_numeric_negative_p(gnc_numeric a)
-{
- if(gnc_numeric_check(a))
- {
- return 0;
- }
- else
- {
- if((a.num < 0) && (a.denom != 0))
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
-}
-
-/********************************************************************
- * gnc_numeric_positive_p
- ********************************************************************/
-
-gboolean
-gnc_numeric_positive_p(gnc_numeric a)
-{
- if(gnc_numeric_check(a))
- {
- return 0;
- }
- else
- {
- if((a.num > 0) && (a.denom != 0))
- {
- return 1;
- }
- else
- {
- return 0;
- }
- }
-}
-
-/********************************************************************
- * gnc_numeric_compare
- * returns 1 if a>b, -1 if b>a, 0 if a == b
- ********************************************************************/
-
-int
-gnc_numeric_compare(gnc_numeric a, gnc_numeric b)
-{
- gint64 aa, bb;
- qofint128 l, r;
-
- if(gnc_numeric_check(a) || gnc_numeric_check(b))
- {
- return 0;
- }
-
- if (a.denom == b.denom)
- {
- if(a.num == b.num) return 0;
- if(a.num > b.num) return 1;
- return -1;
- }
-
- if ((a.denom > 0) && (b.denom > 0))
- {
- /* Avoid overflows using 128-bit intermediate math */
- l = mult128 (a.num, b.denom);
- r = mult128 (b.num, a.denom);
- return cmp128 (l,r);
- }
-
- aa = a.num * a.denom;
- bb = b.num * b.denom;
-
- if(aa == bb) return 0;
- if(aa > bb) return 1;
- return -1;
-}
-
-
-/********************************************************************
- * gnc_numeric_eq
- ********************************************************************/
-
-gboolean
-gnc_numeric_eq(gnc_numeric a, gnc_numeric b)
-{
- return ((a.num == b.num) && (a.denom == b.denom));
-}
-
-
-/********************************************************************
- * gnc_numeric_equal
- ********************************************************************/
-
-gboolean
-gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
-{
- if ((a.denom == b.denom) && (a.denom > 0))
- {
- return (a.num == b.num);
- }
- if ((a.denom > 0) && (b.denom > 0))
- {
- // return (a.num*b.denom == b.num*a.denom);
- qofint128 l = mult128 (a.num, b.denom);
- qofint128 r = mult128 (b.num, a.denom);
- return equal128 (l, r);
-
-#if ALT_WAY_OF_CHECKING_EQUALITY
- gnc_numeric ra = gnc_numeric_reduce (a);
- gnc_numeric rb = gnc_numeric_reduce (b);
- if (ra.denom != rb.denom) return 0;
- if (ra.num != rb.num) return 0;
- return 1;
-#endif
- }
- if ((a.denom < 0) && (b.denom < 0))
- {
- return ((a.num * b.denom) == (a.denom * b.num));
- }
- else
- {
- return 0;
- }
-}
-
-
-/********************************************************************
- * gnc_numeric_same
- * would a and b be equal() if they were both converted to the same
- * denominator?
- ********************************************************************/
-
-int
-gnc_numeric_same(gnc_numeric a, gnc_numeric b, gint64 denom,
- gint how) {
- gnc_numeric aconv, bconv;
-
- aconv = gnc_numeric_convert(a, denom, how);
- bconv = gnc_numeric_convert(b, denom, how);
-
- return(gnc_numeric_equal(aconv, bconv));
-}
-
-
-
-/********************************************************************
- * gnc_numeric_add
- ********************************************************************/
-
-gnc_numeric
-gnc_numeric_add(gnc_numeric a, gnc_numeric b,
- gint64 denom, gint how)
-{
- gnc_numeric sum;
-
- if(gnc_numeric_check(a) || gnc_numeric_check(b))
- {
- return gnc_numeric_error(GNC_ERROR_ARG);
- }
-
- if((denom == GNC_DENOM_AUTO) &&
- (how & GNC_NUMERIC_DENOM_MASK) == GNC_HOW_DENOM_FIXED)
- {
- if(a.denom == b.denom) {
- denom = a.denom;
- }
- else if(b.num == 0) {
- denom = a.denom;
- b.denom = a.denom;
- }
- else if(a.num == 0) {
- denom = b.denom;
- a.denom = b.denom;
- }
- else {
- return gnc_numeric_error(GNC_ERROR_DENOM_DIFF);
- }
- }
-
- if(a.denom < 0)
- {
- a.num *= a.denom;
- a.denom = 1;
- }
-
- if(b.denom < 0)
- {
- b.num *= b.denom;
- b.denom = 1;
- }
-
- /* Get an exact answer.. same denominator is the common case. */
- if(a.denom == b.denom)
- {
- sum.num = a.num + b.num;
- sum.denom = a.denom;
- }
- else
- {
- /* We want to do this:
- * sum.num = a.num*b.denom + b.num*a.denom;
- * sum.denom = a.denom*b.denom;
- * but the multiply could overflow.
- * Computing the LCD minimizes likelyhood of overflow
- */
- gint64 lcd;
- qofint128 ca, cb, cab;
- lcd = gnc_numeric_lcd(a,b);
- if (GNC_ERROR_ARG == lcd)
- {
- return gnc_numeric_error(GNC_ERROR_OVERFLOW);
- }
- ca = mult128 (a.num, lcd/a.denom);
- if (ca.isbig) return gnc_numeric_error(GNC_ERROR_OVERFLOW);
-
- cb = mult128 (b.num, lcd/b.denom);
- if (cb.isbig) return gnc_numeric_error(GNC_ERROR_OVERFLOW);
-
- cab = add128 (ca, cb);
- if (cab.isbig) return gnc_numeric_error(GNC_ERROR_OVERFLOW);
-
- sum.num = cab.lo;
- if (cab.isneg) sum.num = -sum.num;
- sum.denom = lcd;
- }
-
- if((denom == GNC_DENOM_AUTO) &&
- ((how & GNC_NUMERIC_DENOM_MASK) == GNC_HOW_DENOM_LCD))
- {
- denom = gnc_numeric_lcd(a, b);
- how = how & GNC_NUMERIC_RND_MASK;
- }
-
- return gnc_numeric_convert(sum, denom, how);
-}
-
-/********************************************************************
- * gnc_numeric_sub
- ********************************************************************/
-
-gnc_numeric
-gnc_numeric_sub(gnc_numeric a, gnc_numeric b,
- gint64 denom, gint how)
-{
- gnc_numeric nb;
- if(gnc_numeric_check(a) || gnc_numeric_check(b))
- {
- return gnc_numeric_error(GNC_ERROR_ARG);
- }
-
- nb = b;
- nb.num = -nb.num;
- return gnc_numeric_add (a, nb, denom, how);
-}
-
-/********************************************************************
- * gnc_numeric_mul
- ********************************************************************/
-
-gnc_numeric
-gnc_numeric_mul(gnc_numeric a, gnc_numeric b,
- gint64 denom, gint how)
-{
- gnc_numeric product, result;
- qofint128 bignume, bigdeno;
-
- if(gnc_numeric_check(a) || gnc_numeric_check(b)) {
- return gnc_numeric_error(GNC_ERROR_ARG);
- }
-
- if((denom == GNC_DENOM_AUTO) &&
- (how & GNC_NUMERIC_DENOM_MASK) == GNC_HOW_DENOM_FIXED) {
- if(a.denom == b.denom) {
- denom = a.denom;
- }
- else if(b.num == 0) {
- denom = a.denom;
- }
- else if(a.num == 0) {
- denom = b.denom;
- }
- else {
- return gnc_numeric_error(GNC_ERROR_DENOM_DIFF);
- }
- }
-
- if((denom == GNC_DENOM_AUTO) &&
- ((how & GNC_NUMERIC_DENOM_MASK) == GNC_HOW_DENOM_LCD))
- {
- denom = gnc_numeric_lcd(a, b);
- how = how & GNC_NUMERIC_RND_MASK;
- }
-
- if(a.denom < 0) {
- a.num *= a.denom;
- a.denom = 1;
- }
-
- if(b.denom < 0) {
- b.num *= b.denom;
- b.denom = 1;
- }
-
- bignume = mult128 (a.num, b.num);
- bigdeno = mult128 (a.denom, b.denom);
- product.num = a.num*b.num;
- product.denom = a.denom*b.denom;
-
- /* If it looks to be overflowing, try to reduce the fraction ... */
- if (bignume.isbig || bigdeno.isbig)
- {
- gint64 tmp;
- a = gnc_numeric_reduce (a);
- b = gnc_numeric_reduce (b);
- tmp = a.num;
- a.num = b.num;
- b.num = tmp;
- a = gnc_numeric_reduce (a);
- b = gnc_numeric_reduce (b);
-
- bignume = mult128 (a.num, b.num);
- bigdeno = mult128 (a.denom, b.denom);
- product.num = a.num*b.num;
- product.denom = a.denom*b.denom;
- }
-
- /* If it its still overflowing, and rounding is allowed then round */
- if (bignume.isbig || bigdeno.isbig)
- {
- /* If rounding allowed, then shift until there's no
- * more overflow. The conversion at the end will fix
- * things up for the final value. Else overflow. */
- if ((how & GNC_NUMERIC_RND_MASK) == GNC_HOW_RND_NEVER)
- {
- if (bigdeno.isbig)
- {
- return gnc_numeric_error (GNC_ERROR_OVERFLOW);
- }
- product = reduce128 (bignume, product.denom);
- if (gnc_numeric_check (product))
- {
- return gnc_numeric_error (GNC_ERROR_OVERFLOW);
- }
- }
- else
- {
- while (bignume.isbig || bigdeno.isbig)
- {
- bignume = shift128 (bignume);
- bigdeno = shift128 (bigdeno);
- }
- product.num = bignume.lo;
- if (bignume.isneg) product.num = -product.num;
-
- product.denom = bigdeno.lo;
- if (0 == product.denom)
- {
- return gnc_numeric_error (GNC_ERROR_OVERFLOW);
- }
- }
- }
-
-#if 0 /* currently, product denom won't ever be zero */
- if(product.denom < 0) {
- product.num = -product.num;
- product.denom = -product.denom;
- }
-#endif
-
- result = gnc_numeric_convert(product, denom, how);
- return result;
-}
-
-
-/********************************************************************
- * gnc_numeric_div
- ********************************************************************/
-
-gnc_numeric
-gnc_numeric_div(gnc_numeric a, gnc_numeric b,
- gint64 denom, gint how)
-{
- gnc_numeric quotient;
- qofint128 nume, deno;
-
- if(gnc_numeric_check(a) || gnc_numeric_check(b))
- {
- return gnc_numeric_error(GNC_ERROR_ARG);
- }
-
- if((denom == GNC_DENOM_AUTO) &&
- (how & GNC_NUMERIC_DENOM_MASK) == GNC_HOW_DENOM_FIXED)
- {
- if(a.denom == b.denom)
- {
- denom = a.denom;
- }
- else if(a.denom == 0)
- {
- denom = b.denom;
- }
- else
- {
- return gnc_numeric_error(GNC_ERROR_DENOM_DIFF);
- }
- }
-
-
- if(a.denom < 0)
- {
- a.num *= a.denom;
- a.denom = 1;
- }
-
- if(b.denom < 0)
- {
- b.num *= b.denom;
- b.denom = 1;
- }
-
- if(a.denom == b.denom)
- {
- quotient.num = a.num;
- quotient.denom = b.num;
- }
- else
- {
- gint64 sgn = 1;
- if (0 > a.num)
- {
- sgn = -sgn;
- a.num = -a.num;
- }
- if (0 > b.num)
- {
- sgn = -sgn;
- b.num = -b.num;
- }
- nume = mult128(a.num, b.denom);
- deno = mult128(b.num, a.denom);
-
- /* Try to avoid overflow by removing common factors */
- if (nume.isbig && deno.isbig)
- {
- gnc_numeric ra = gnc_numeric_reduce (a);
- gnc_numeric rb = gnc_numeric_reduce (b);
-
- gint64 gcf_nume = gcf64(ra.num, rb.num);
- gint64 gcf_deno = gcf64(rb.denom, ra.denom);
- nume = mult128(ra.num/gcf_nume, rb.denom/gcf_deno);
- deno = mult128(rb.num/gcf_nume, ra.denom/gcf_deno);
- }
-
- if ((0 == nume.isbig) && (0 == deno.isbig))
- {
- quotient.num = sgn * nume.lo;
- quotient.denom = deno.lo;
- goto dive_done;
- }
- else if (0 == deno.isbig)
- {
- quotient = reduce128 (nume, deno.lo);
- if (0 == gnc_numeric_check (quotient))
- {
- quotient.num *= sgn;
- goto dive_done;
- }
- }
-
- /* If rounding allowed, then shift until there's no
- * more overflow. The conversion at the end will fix
- * things up for the final value. */
- if ((how & GNC_NUMERIC_RND_MASK) == GNC_HOW_RND_NEVER)
- {
- return gnc_numeric_error (GNC_ERROR_OVERFLOW);
- }
- while (nume.isbig || deno.isbig)
- {
- nume = shift128 (nume);
- deno = shift128 (deno);
- }
- quotient.num = sgn * nume.lo;
- quotient.denom = deno.lo;
- if (0 == quotient.denom)
- {
- return gnc_numeric_error (GNC_ERROR_OVERFLOW);
- }
- }
-
- if(quotient.denom < 0)
- {
- quotient.num = -quotient.num;
- quotient.denom = -quotient.denom;
- }
-
-dive_done:
- if((denom == GNC_DENOM_AUTO) &&
- ((how & GNC_NUMERIC_DENOM_MASK) == GNC_HOW_DENOM_LCD))
- {
- denom = gnc_numeric_lcd(a, b);
- how = how & GNC_NUMERIC_RND_MASK;
- }
-
- return gnc_numeric_convert(quotient, denom, how);
-}
-
-/********************************************************************
- * gnc_numeric_neg
- * negate the argument
- ********************************************************************/
-
-gnc_numeric
-gnc_numeric_neg(gnc_numeric a) {
- if(gnc_numeric_check(a)) {
- return gnc_numeric_error(GNC_ERROR_ARG);
- }
- return gnc_numeric_create(- a.num, a.denom);
-}
-
-/********************************************************************
- * gnc_numeric_neg
- * return the absolute value of the argument
- ********************************************************************/
-
-gnc_numeric
-gnc_numeric_abs(gnc_numeric a)
-{
- if(gnc_numeric_check(a)) {
- return gnc_numeric_error(GNC_ERROR_ARG);
- }
- return gnc_numeric_create(ABS(a.num), a.denom);
-}
-
-/********************************************************************
- * gnc_numeric_convert
- ********************************************************************/
-
-gnc_numeric
-gnc_numeric_convert(gnc_numeric in, gint64 denom, gint how)
-{
- gnc_numeric out;
- gnc_numeric temp;
- gint64 temp_bc;
- gint64 temp_a;
- gint64 remainder;
- gint64 sign;
- gint denom_neg=0;
- double ratio, logratio;
- double sigfigs;
- qofint128 nume, newm;
-
- temp.num = 0;
- temp.denom = 0;
-
- if(gnc_numeric_check(in)) {
- return gnc_numeric_error(GNC_ERROR_ARG);
- }
-
- if(denom == GNC_DENOM_AUTO)
- {
- switch(how & GNC_NUMERIC_DENOM_MASK)
- {
- default:
- case GNC_HOW_DENOM_LCD: /* LCD is meaningless with AUTO in here */
- case GNC_HOW_DENOM_EXACT:
- return in;
- break;
-
- case GNC_HOW_DENOM_REDUCE:
- /* reduce the input to a relatively-prime fraction */
- return gnc_numeric_reduce(in);
- break;
-
- case GNC_HOW_DENOM_FIXED:
- if(in.denom != denom) {
- return gnc_numeric_error(GNC_ERROR_DENOM_DIFF);
- }
- else {
- return in;
- }
- break;
-
- case GNC_HOW_DENOM_SIGFIG:
- ratio = fabs(gnc_numeric_to_double(in));
- if(ratio < 10e-20) {
- logratio = 0;
- }
- else {
- logratio = log10(ratio);
- logratio = ((logratio > 0.0) ?
- (floor(logratio)+1.0) : (ceil(logratio)));
- }
- sigfigs = GNC_HOW_GET_SIGFIGS(how);
-
- if(sigfigs-logratio >= 0) {
- denom = (gint64)(pow(10, sigfigs-logratio));
- }
- else {
- denom = -((gint64)(pow(10, logratio-sigfigs)));
- }
-
- how = how & ~GNC_HOW_DENOM_SIGFIG & ~GNC_NUMERIC_SIGFIGS_MASK;
- break;
-
- }
- }
-
- /* Make sure we need to do the work */
- if(in.denom == denom) {
- return in;
- }
-
- /* If the denominator of the input value is negative, get rid of that. */
- if(in.denom < 0) {
- in.num = in.num * (- in.denom);
- in.denom = 1;
- }
-
- sign = (in.num < 0) ? -1 : 1;
-
- /* If the denominator is less than zero, we are to interpret it as
- * the reciprocal of its magnitude. */
- if(denom < 0)
- {
-
- /* XXX FIXME: use 128-bit math here ... */
- denom = - denom;
- denom_neg = 1;
- temp_a = (in.num < 0) ? -in.num : in.num;
- temp_bc = in.denom * denom;
- remainder = in.num % temp_bc;
- out.num = in.num / temp_bc;
- out.denom = - denom;
- }
- else
- {
- /* Do all the modulo and int division on positive values to make
- * things a little clearer. Reduce the fraction denom/in.denom to
- * help with range errors */
- temp.num = denom;
- temp.denom = in.denom;
- temp = gnc_numeric_reduce(temp);
-
- /* Symbolically, do the following:
- * out.num = in.num * temp.num;
- * remainder = out.num % temp.denom;
- * out.num = out.num / temp.denom;
- * out.denom = denom;
- */
- nume = mult128 (in.num, temp.num);
- newm = div128 (nume, temp.denom);
- remainder = rem128 (nume, temp.denom);
-
- if (newm.isbig)
- {
- return gnc_numeric_error(GNC_ERROR_OVERFLOW);
- }
-
- out.num = newm.lo;
- out.denom = denom;
- }
-
- if (remainder)
- {
- switch(how & GNC_NUMERIC_RND_MASK)
- {
- case GNC_HOW_RND_FLOOR:
- if(sign < 0) {
- out.num = out.num + 1;
- }
- break;
-
- case GNC_HOW_RND_CEIL:
- if(sign > 0) {
- out.num = out.num + 1;
- }
- break;
-
- case GNC_HOW_RND_TRUNC:
- break;
-
- case GNC_HOW_RND_PROMOTE:
- out.num = out.num + 1;
- break;
-
- case GNC_HOW_RND_ROUND_HALF_DOWN:
- if(denom_neg)
- {
- if((2 * remainder) > in.denom*denom)
- {
- out.num = out.num + 1;
- }
- }
- else if((2 * remainder) > temp.denom)
- {
- out.num = out.num + 1;
- }
- /* check that 2*remainder didn't over-flow */
- else if (((2 * remainder) < remainder) &&
- (remainder > (temp.denom / 2)))
- {
- out.num = out.num + 1;
- }
- break;
-
- case GNC_HOW_RND_ROUND_HALF_UP:
- if(denom_neg)
- {
- if((2 * remainder) >= in.denom*denom)
- {
- out.num = out.num + 1;
- }
- }
- else if((2 * remainder ) >= temp.denom)
- {
- out.num = out.num + 1;
- }
- /* check that 2*remainder didn't over-flow */
- else if (((2 * remainder) < remainder) &&
- (remainder >= (temp.denom / 2)))
- {
- out.num = out.num + 1;
- }
- break;
-
- case GNC_HOW_RND_ROUND:
- if(denom_neg)
- {
- if((2 * remainder) > in.denom*denom)
- {
- out.num = out.num + 1;
- }
- else if((2 * remainder) == in.denom*denom)
- {
- if(out.num % 2)
- {
- out.num = out.num + 1;
- }
- }
- }
- else
- {
- if((2 * remainder ) > temp.denom)
- {
- out.num = out.num + 1;
- }
- /* check that 2*remainder didn't over-flow */
- else if (((2 * remainder) < remainder) &&
- (remainder > (temp.denom / 2)))
- {
- out.num = out.num + 1;
- }
- else if((2 * remainder) == temp.denom)
- {
- if(out.num % 2)
- {
- out.num = out.num + 1;
- }
- }
- /* check that 2*remainder didn't over-flow */
- else if (((2 * remainder) < remainder) &&
- (remainder == (temp.denom / 2)))
- {
- if(out.num % 2)
- {
- out.num = out.num + 1;
- }
- }
- }
- break;
-
- case GNC_HOW_RND_NEVER:
- return gnc_numeric_error(GNC_ERROR_REMAINDER);
- break;
- }
- }
-
- out.num = (sign > 0) ? out.num : (-out.num);
-
- return out;
-}
-
-
-/********************************************************************
- ** reduce a fraction by GCF elimination. This is NOT done as a
- * part of the arithmetic API unless GNC_HOW_DENOM_REDUCE is specified
- * as the output denominator.
- ********************************************************************/
-
-gnc_numeric
-gnc_numeric_reduce(gnc_numeric in)
-{
- gint64 t;
- gint64 num = (in.num < 0) ? (- in.num) : in.num ;
- gint64 denom = in.denom;
- gnc_numeric out;
-
- if(gnc_numeric_check(in))
- {
- return gnc_numeric_error(GNC_ERROR_ARG);
- }
-
- /* The strategy is to use Euclid's algorithm */
- while (denom > 0) {
- t = num % denom;
- num = denom;
- denom = t;
- }
- /* num now holds the GCD (Greatest Common Divisor) */
-
- /* All calculations are done on positive num, since it's not
- * well defined what % does for negative values */
- out.num = in.num / num;
- out.denom = in.denom / num;
- return out;
-}
-
-/********************************************************************
- * double_to_gnc_numeric
- ********************************************************************/
-
-gnc_numeric
-double_to_gnc_numeric(double in, gint64 denom, gint how)
-{
- gnc_numeric out;
- gint64 int_part=0;
- double frac_part;
- gint64 frac_int=0;
- double logval;
- double sigfigs;
-
- if((denom == GNC_DENOM_AUTO) && (how & GNC_HOW_DENOM_SIGFIG))
- {
- if(fabs(in) < 10e-20) {
- logval = 0;
- }
- else {
- logval = log10(fabs(in));
- logval = ((logval > 0.0) ?
- (floor(logval)+1.0) : (ceil(logval)));
- }
- sigfigs = GNC_HOW_GET_SIGFIGS(how);
- if(sigfigs-logval >= 0) {
- denom = (gint64)(pow(10, sigfigs-logval));
- }
- else {
- denom = -((gint64)(pow(10, logval-sigfigs)));
- }
-
- how = how & ~GNC_HOW_DENOM_SIGFIG & ~GNC_NUMERIC_SIGFIGS_MASK;
- }
-
- int_part = (gint64)(floor(fabs(in)));
- frac_part = in - (double)int_part;
-
- int_part = int_part * denom;
- frac_part = frac_part * (double)denom;
-
- switch(how & GNC_NUMERIC_RND_MASK) {
- case GNC_HOW_RND_FLOOR:
- frac_int = (gint64)floor(frac_part);
- break;
-
- case GNC_HOW_RND_CEIL:
- frac_int = (gint64)ceil(frac_part);
- break;
-
- case GNC_HOW_RND_TRUNC:
- frac_int = (gint64)frac_part;
- break;
-
- case GNC_HOW_RND_ROUND:
- case GNC_HOW_RND_ROUND_HALF_UP:
- frac_int = (gint64)rint(frac_part);
- break;
-
- case GNC_HOW_RND_NEVER:
- frac_int = (gint64)floor(frac_part);
- if(frac_part != (double) frac_int) {
- /* signal an error */
- }
- break;
- }
-
- out.num = int_part + frac_int;
- out.denom = denom;
- return out;
-}
-
-/********************************************************************
- * gnc_numeric_to_double
- ********************************************************************/
-
-double
-gnc_numeric_to_double(gnc_numeric in)
-{
- if(in.denom > 0)
- {
- return (double)in.num/(double)in.denom;
- }
- else
- {
- return (double)(in.num * in.denom);
- }
-}
-
-/********************************************************************
- * gnc_numeric_error
- ********************************************************************/
-
-gnc_numeric
-gnc_numeric_error(GNCNumericErrorCode error_code)
-{
- return gnc_numeric_create(error_code, 0LL);
-}
-
-
-/********************************************************************
- * gnc_numeric_add_with_error
- ********************************************************************/
-
-gnc_numeric
-gnc_numeric_add_with_error(gnc_numeric a, gnc_numeric b,
- gint64 denom, gint how,
- gnc_numeric * error)
-{
-
- gnc_numeric sum = gnc_numeric_add(a, b, denom, how);
- gnc_numeric exact = gnc_numeric_add(a, b, GNC_DENOM_AUTO,
- GNC_HOW_DENOM_REDUCE);
- gnc_numeric err = gnc_numeric_sub(sum, exact, GNC_DENOM_AUTO,
- GNC_HOW_DENOM_REDUCE);
-
- if(error) {
- *error = err;
- }
- return sum;
-}
-
-/********************************************************************
- * gnc_numeric_sub_with_error
- ********************************************************************/
-
-gnc_numeric
-gnc_numeric_sub_with_error(gnc_numeric a, gnc_numeric b,
- gint64 denom, gint how,
- gnc_numeric * error)
-{
- gnc_numeric diff = gnc_numeric_sub(a, b, denom, how);
- gnc_numeric exact = gnc_numeric_sub(a, b, GNC_DENOM_AUTO,
- GNC_HOW_DENOM_REDUCE);
- gnc_numeric err = gnc_numeric_sub(diff, exact, GNC_DENOM_AUTO,
- GNC_HOW_DENOM_REDUCE);
- if(error) {
- *error = err;
- }
- return diff;
-}
-
-
-/********************************************************************
- * gnc_numeric_mul_with_error
- ********************************************************************/
-
-gnc_numeric
-gnc_numeric_mul_with_error(gnc_numeric a, gnc_numeric b,
- gint64 denom, gint how,
- gnc_numeric * error)
-{
- gnc_numeric prod = gnc_numeric_mul(a, b, denom, how);
- gnc_numeric exact = gnc_numeric_mul(a, b, GNC_DENOM_AUTO,
- GNC_HOW_DENOM_REDUCE);
- gnc_numeric err = gnc_numeric_sub(prod, exact, GNC_DENOM_AUTO,
- GNC_HOW_DENOM_REDUCE);
- if(error) {
- *error = err;
- }
- return prod;
-}
-
-
-/********************************************************************
- * gnc_numeric_div_with_error
- ********************************************************************/
-
-gnc_numeric
-gnc_numeric_div_with_error(gnc_numeric a, gnc_numeric b,
- gint64 denom, gint how,
- gnc_numeric * error)
-{
- gnc_numeric quot = gnc_numeric_div(a, b, denom, how);
- gnc_numeric exact = gnc_numeric_div(a, b, GNC_DENOM_AUTO,
- GNC_HOW_DENOM_REDUCE);
- gnc_numeric err = gnc_numeric_sub(quot, exact,
- GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE);
- if(error) {
- *error = err;
- }
- return quot;
-}
-
-/********************************************************************
- * gnc_numeric text IO
- ********************************************************************/
-
-gchar *
-gnc_numeric_to_string(gnc_numeric n)
-{
- gchar *result;
- gint64 tmpnum = n.num;
- gint64 tmpdenom = n.denom;
-
- result = g_strdup_printf("%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT, tmpnum, tmpdenom);
-
- return result;
-}
-
-gchar *
-gnc_num_dbg_to_string(gnc_numeric n)
-{
- static char buff[1000];
- static char *p = buff;
- gint64 tmpnum = n.num;
- gint64 tmpdenom = n.denom;
-
- p+= 100;
- if (p-buff >= 1000) p = buff;
-
- sprintf(p, "%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT, tmpnum, tmpdenom);
-
- return p;
-}
-
-gboolean
-string_to_gnc_numeric(const gchar* str, gnc_numeric *n)
-{
- size_t num_read;
- gint64 tmpnum;
- gint64 tmpdenom;
-
- if(!str) return FALSE;
-
-#ifdef GNC_DEPRECATED
- /* must use "<" here because %n's effects aren't well defined */
- if(sscanf(str, " " GNC_SCANF_LLD "/" GNC_SCANF_LLD "%n",
- &tmpnum, &tmpdenom, &num_read) < 2) {
- return FALSE;
- }
-#else
- tmpnum = strtoll (str, NULL, 0);
- str = strchr (str, '/');
- if (!str) return FALSE;
- str ++;
- tmpdenom = strtoll (str, NULL, 0);
- num_read = strspn (str, "0123456789");
-#endif
- n->num = tmpnum;
- n->denom = tmpdenom;
- return TRUE;
-}
-
-/********************************************************************
- * gnc_numeric misc testing
- ********************************************************************/
-#ifdef _GNC_NUMERIC_TEST
-
-static char *
-gnc_numeric_print(gnc_numeric in)
-{
- char * retval;
- if(gnc_numeric_check(in)) {
- retval = g_strdup_printf("<ERROR> [%" G_GINT64_FORMAT " / %" G_GINT64_FORMAT "]",
- in.num,
- in.denom);
- }
- else {
- retval = g_strdup_printf("[%" G_GINT64_FORMAT " / %" G_GINT64_FORMAT "]",
- in.num,
- in.denom);
- }
- return retval;
-}
-
-int
-main(int argc, char ** argv)
-{
- gnc_numeric a = gnc_numeric_create(1, 3);
- gnc_numeric b = gnc_numeric_create(1, 4);
- gnc_numeric c;
-
- gnc_numeric err;
-
- c = gnc_numeric_add_with_error(a, b, 100, GNC_HOW_RND_ROUND, &err);
- printf("add 100ths/error : %s + %s = %s + (error) %s\n\n",
- gnc_numeric_print(a), gnc_numeric_print(b),
- gnc_numeric_print(c),
- gnc_numeric_print(err));
-
- c = gnc_numeric_sub_with_error(a, b, 100, GNC_HOW_RND_FLOOR, &err);
- printf("sub 100ths/error : %s - %s = %s + (error) %s\n\n",
- gnc_numeric_print(a), gnc_numeric_print(b),
- gnc_numeric_print(c),
- gnc_numeric_print(err));
-
- c = gnc_numeric_mul_with_error(a, b, 100, GNC_HOW_RND_ROUND, &err);
- printf("mul 100ths/error : %s * %s = %s + (error) %s\n\n",
- gnc_numeric_print(a), gnc_numeric_print(b),
- gnc_numeric_print(c),
- gnc_numeric_print(err));
-
- c = gnc_numeric_div_with_error(a, b, 100, GNC_HOW_RND_ROUND, &err);
- printf("div 100ths/error : %s / %s = %s + (error) %s\n\n",
- gnc_numeric_print(a), gnc_numeric_print(b),
- gnc_numeric_print(c),
- gnc_numeric_print(err));
-
- printf("multiply (EXACT): %s * %s = %s\n",
- gnc_numeric_print(a), gnc_numeric_print(b),
- gnc_numeric_print(gnc_numeric_mul(a, b, GNC_DENOM_AUTO, GNC_HOW_DENOM_EXACT)));
-
- printf("multiply (REDUCE): %s * %s = %s\n",
- gnc_numeric_print(a), gnc_numeric_print(b),
- gnc_numeric_print(gnc_numeric_mul(a, b, GNC_DENOM_AUTO, GNC_HOW_DENOM_REDUCE)));
-
-
- return 0;
-}
-#endif
-
-/* ======================== END OF FILE =================== */
Deleted: gnucash/trunk/src/engine/gnc-numeric.h
===================================================================
--- gnucash/trunk/src/engine/gnc-numeric.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/gnc-numeric.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,515 +0,0 @@
-/********************************************************************
- * gnc-numeric.h - A rational number library *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
- *******************************************************************/
-
-/** @addtogroup Numeric
-
- The 'Numeric' functions provide a way of working with rational
- numbers while maintaining strict control over rounding errors
- when adding rationals with different denominators. The Numeric
- class is primarily used for working with monetary amounts,
- where the denominator typically represents the smallest fraction
- of the currency (e.g. pennies, centimes). The numeric class
- can handle any fraction (e.g. twelfth's) and is not limited
- to fractions that are powers of ten.
-
- A 'Numeric' value represents a number in rational form, with a
- 64-bit integer as numerator and denominator. Rationals are
- ideal for many uses, such as performing exact, roundoff-error-free
- addition and multiplication, but 64-bit rationals do not have
- the dynamic range of floating point numbers.
-
-EXAMPLE\n
--------\n
-The following program finds the best ::gnc_numeric approximation to
-the \a math.h constant \a M_PI given a maximum denominator. For
-large denominators, the ::gnc_numeric approximation is accurate to
-more decimal places than will generally be needed, but in some cases
-this may not be good enough. For example,
-
- at verbatim
- M_PI = 3.14159265358979323846
- 245850922 / 78256779 = 3.14159265358979311599 (16 sig figs)
- 3126535 / 995207 = 3.14159265358865047446 (12 sig figs)
- 355 / 113 = 3.14159292035398252096 (7 sig figs)
- at endverbatim
-
- at verbatim
-#include <glib.h>
-#include "gnc-numeric.h"
-#include <math.h>
-
-int
-main(int argc, char ** argv)
-{
- gnc_numeric approx, best;
- double err, best_err=1.0;
- double m_pi = M_PI;
- gint64 denom;
- gint64 max;
-
- sscanf(argv[1], "%Ld", &max);
-
- for (denom = 1; denom < max; denom++)
- {
- approx = double_to_gnc_numeric (m_pi, denom, GNC_RND_ROUND);
- err = m_pi - gnc_numeric_to_double (approx);
- if (fabs (err) < fabs (best_err))
- {
- best = approx;
- best_err = err;
- printf ("%Ld / %Ld = %.30f\n", gnc_numeric_num (best),
- gnc_numeric_denom (best), gnc_numeric_to_double (best));
- }
- }
-}
- at endverbatim
-
-@{ */
-/** @file gnc-numeric.h
- @brief An exact-rational-number library for gnucash.
- @author Copyright (C) 2000 Bill Gribble
- @author Copyright (C) 2004 Linas Vepstas <linas at linas.org>
-*/
-
-
-#ifndef GNC_NUMERIC_H
-#define GNC_NUMERIC_H
-
-#include <glib.h>
-
-struct _gnc_numeric
-{
- gint64 num;
- gint64 denom;
-};
-
-/** @brief An rational-number type
- *
- * This is a rational number, defined by numerator and denominator. */
-typedef struct _gnc_numeric gnc_numeric;
-
-/** @name Arguments Standard Arguments to most functions
-
- Most of the gnc_numeric arithmetic functions take two arguments
- in addition to their numeric args: 'denom', which is the denominator
- to use in the output gnc_numeric object, and 'how'. which
- describes how the arithmetic result is to be converted to that
- denominator. This combination of output denominator and rounding policy
- allows the results of financial and other rational computations to be
- properly rounded to the appropriate units.
-
- Valid values for denom are:
- GNC_DENOM_AUTO -- compute denominator exactly
- integer n -- Force the denominator of the result to be this integer
- GNC_DENOM_RECIPROCAL -- Use 1/n as the denominator (???huh???)
-
- Valid values for 'how' are bitwise combinations of zero or one
- "rounding instructions" with zero or one "denominator types".
- Valid rounding instructions are:
- GNC_HOW_RND_FLOOR
- GNC_HOW_RND_CEIL
- GNC_HOW_RND_TRUNC
- GNC_HOW_RND_PROMOTE
- GNC_HOW_RND_ROUND_HALF_DOWN
- GNC_HOW_RND_ROUND_HALF_UP
- GNC_HOW_RND_ROUND
- GNC_HOW_RND_NEVER
-
- The denominator type specifies how to compute a denominator if
- GNC_DENOM_AUTO is specified as the 'denom'. Valid
- denominator types are:
- GNC_HOW_DENOM_EXACT
- GNC_HOW_DENOM_REDUCE
- GNC_HOW_DENOM_LCD
- GNC_HOW_DENOM_FIXED
- GNC_HOW_DENOM_SIGFIGS(N)
-
- To use traditional rational-number operational semantics (all results
- are exact and are reduced to relatively-prime fractions) pass the
- argument GNC_DENOM_AUTO as 'denom' and
- GNC_HOW_DENOM_REDUCE| GNC_HOW_RND_NEVER as 'how'.
-
- To enforce strict financial semantics (such that all operands must have
- the same denominator as each other and as the result), use
- GNC_DENOM_AUTO as 'denom' and
- GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER as 'how'.
-@{
-*/
-
-/** \brief bitmasks for HOW flags.
-
- * bits 8-15 of 'how' are reserved for the number of significant
- * digits to use in the output with GNC_HOW_DENOM_SIGFIG
- */
-#define GNC_NUMERIC_RND_MASK 0x0000000f
-#define GNC_NUMERIC_DENOM_MASK 0x000000f0
-#define GNC_NUMERIC_SIGFIGS_MASK 0x0000ff00
-
-/** \brief Rounding/Truncation modes for operations.
-
- * Rounding instructions control how fractional parts in the specified
- * denominator affect the result. For example, if a computed result is
- * "3/4" but the specified denominator for the return value is 2, should
- * the return value be "1/2" or "2/2"?
- *
- * Possible rounding instructions are:
- */
-enum {
- /** Round toward -infinity */
- GNC_HOW_RND_FLOOR = 0x01,
-
- /** Round toward +infinity */
- GNC_HOW_RND_CEIL = 0x02,
-
- /** Truncate fractions (round toward zero) */
- GNC_HOW_RND_TRUNC = 0x03,
-
- /** Promote fractions (round away from zero) */
- GNC_HOW_RND_PROMOTE = 0x04,
-
- /** Round to the nearest integer, rounding toward zero
- * when there are two equidistant nearest integers.
- */
- GNC_HOW_RND_ROUND_HALF_DOWN = 0x05,
-
- /** Round to the nearest integer, rounding away from zero
- * when there are two equidistant nearest integers.
- */
- GNC_HOW_RND_ROUND_HALF_UP = 0x06,
-
- /** Use unbiased ("banker's") rounding. This rounds to the
- * nearest integer, and to the nearest even integer when there
- * are two equidistant nearest integers. This is generally the
- * one you should use for financial quantities.
- */
- GNC_HOW_RND_ROUND = 0x07,
-
- /** Never round at all, and signal an error if there is a
- * fractional result in a computation.
- */
- GNC_HOW_RND_NEVER = 0x08
-};
-
-/** How to compute a denominator, or'ed into the "how" field. */
-enum {
- /** Use any denominator which gives an exactly correct ratio of
- * numerator to denominator. Use EXACT when you do not wish to
- * lose any information in the result but also do not want to
- * spend any time finding the "best" denominator.
- */
- GNC_HOW_DENOM_EXACT = 0x10,
-
- /** Reduce the result value by common factor elimination,
- * using the smallest possible value for the denominator that
- * keeps the correct ratio. The numerator and denominator of
- * the result are relatively prime.
- */
- GNC_HOW_DENOM_REDUCE = 0x20,
-
- /** Find the least common multiple of the arguments' denominators
- * and use that as the denominator of the result.
- */
- GNC_HOW_DENOM_LCD = 0x30,
-
- /** All arguments are required to have the same denominator,
- * that denominator is to be used in the output, and an error
- * is to be signaled if any argument has a different denominator.
- */
- GNC_HOW_DENOM_FIXED = 0x40,
-
- /** Round to the number of significant figures given in the rounding
- * instructions by the GNC_HOW_DENOM_SIGFIGS () macro.
- */
- GNC_HOW_DENOM_SIGFIG = 0x50
-};
-
-/** Build a 'how' value that will generate a denominator that will
- * keep at least n significant figures in the result.
- */
-#define GNC_HOW_DENOM_SIGFIGS( n ) ( ((( n ) & 0xff) << 8) | GNC_HOW_DENOM_SIGFIG)
-#define GNC_HOW_GET_SIGFIGS( a ) ( (( a ) & 0xff00 ) >> 8)
-
-/** Error codes */
-typedef enum {
- GNC_ERROR_OK = 0, /**< No error */
- GNC_ERROR_ARG = -1, /**< Argument is not a valid number */
- GNC_ERROR_OVERFLOW = -2, /**< Intermediate result overflow */
-
- /** GNC_HOW_DENOM_FIXED was specified, but argument denominators differed. */
- GNC_ERROR_DENOM_DIFF = -3,
-
- /** GNC_HOW_RND_NEVER was specified, but the result could not be
- * converted to the desired denominator without a remainder. */
- GNC_ERROR_REMAINDER = -4
-} GNCNumericErrorCode;
-
-
-/** Values that can be passed as the 'denom' argument.
- * The include a positive number n to be used as the
- * denominator of the output value. Other possibilities
- * include the list below:
- */
-
-/** Compute an appropriate denominator automatically. Flags in
- * the 'how' argument will specify how to compute the denominator.
- */
-#define GNC_DENOM_AUTO 0
-
-/** Use the value 1/n as the denominator of the output value. */
-#define GNC_DENOM_RECIPROCAL( a ) (- ( a ))
-
-/** @} */
-
-/** @name Constructors
-@{
-*/
-/** Make a gnc_numeric from numerator and denominator */
-static inline
-gnc_numeric gnc_numeric_create(gint64 num, gint64 denom) {
- gnc_numeric out;
- out.num = num;
- out.denom = denom;
- return out;
-}
-
-/** create a zero-value gnc_numeric */
-static inline
-gnc_numeric gnc_numeric_zero(void) { return gnc_numeric_create(0, 1); }
-
-/** Convert a floating-point number to a gnc_numeric.
- * Both 'denom' and 'how' are used as in arithmetic,
- * but GNC_DENOM_AUTO is not recognized; a denominator
- * must be specified either explicitctly or through sigfigs.
- */
-gnc_numeric double_to_gnc_numeric(double in, gint64 denom,
- gint how);
-
-/** Read a gnc_numeric from str, skipping any leading whitespace.
- * Return TRUE on success and store the resulting value in "n".
- * Return NULL on error. */
-gboolean string_to_gnc_numeric(const gchar* str, gnc_numeric *n);
-
-/** Create a gnc_numeric object that signals the error condition
- * noted by error_code, rather than a number.
- */
-gnc_numeric gnc_numeric_error(GNCNumericErrorCode error_code);
-/** @} */
-
-/** @name Value Accessors
- @{
-*/
-/** Return numerator */
-static inline
-gint64 gnc_numeric_num(gnc_numeric a) { return a.num; }
-/** Return denominator */
-static inline
-gint64 gnc_numeric_denom(gnc_numeric a) { return a.denom; }
-
-/** Convert numeric to floating-point value. */
-double gnc_numeric_to_double(gnc_numeric in);
-
-/** Convert to string. The returned buffer is to be g_free'd by the
- * caller (it was allocated through g_strdup) */
-gchar *gnc_numeric_to_string(gnc_numeric n);
-
-/** Convert to string. Uses a static, non-thread-safe buffer.
- * For internal use only. */
-gchar * gnc_num_dbg_to_string(gnc_numeric n);
-/** @}*/
-
-/** @name Comparisons and Predicates
- @{
-*/
-/** Check for error signal in value. Returns GNC_ERROR_OK (==0) if
- * the number appears to be valid, otherwise it returns the
- * type of error. Error values always have a denominator of zero.
- */
-GNCNumericErrorCode gnc_numeric_check(gnc_numeric a);
-
-/** Returns 1 if a>b, -1 if b>a, 0 if a == b */
-int gnc_numeric_compare(gnc_numeric a, gnc_numeric b);
-
-/** Returns 1 if the given gnc_numeric is 0 (zero), else returns 0. */
-gboolean gnc_numeric_zero_p(gnc_numeric a);
-
-/** Returns 1 if a < 0, otherwise returns 0. */
-gboolean gnc_numeric_negative_p(gnc_numeric a);
-
-/** Returns 1 if a > 0, otherwise returns 0. */
-gboolean gnc_numeric_positive_p(gnc_numeric a);
-
-/** Equivalence predicate: Returns TRUE (1) if a and b are
- * exactly the same (have the same numerator and denominator)
- */
-gboolean gnc_numeric_eq(gnc_numeric a, gnc_numeric b);
-
-/** Equivalence predicate: Returns TRUE (1) if a and b represent
- * the same number. That is, return TRUE if the ratios, when
- * reduced by eliminating common factors, are identical.
- */
-gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b);
-
-/** Equivalence predicate:
- * Convert both a and b to denom using the
- * specified DENOM and method HOW, and compare numerators
- * the results using gnc_numeric_equal.
- *
- For example, if a == 7/16 and b == 3/4,
- gnc_numeric_same(a, b, 2, GNC_HOW_RND_TRUNC) == 1
- because both 7/16 and 3/4 round to 1/2 under truncation. However,
- gnc_numeric_same(a, b, 2, GNC_HOW_RND_ROUND) == 0
- because 7/16 rounds to 1/2 under unbiased rounding but 3/4 rounds
- to 2/2.
- */
-int gnc_numeric_same(gnc_numeric a, gnc_numeric b,
- gint64 denom, gint how);
-/** @} */
-
-/** @name Arithmetic Operations
- @{
-*/
-/** Return a+b. */
-gnc_numeric gnc_numeric_add(gnc_numeric a, gnc_numeric b,
- gint64 denom, gint how);
-
-/** Return a-b. */
-gnc_numeric gnc_numeric_sub(gnc_numeric a, gnc_numeric b,
- gint64 denom, gint how);
-
-/** Multiply a times b, returning the product. An overflow
- * may occur if the result of the multiplication can't
- * be represented as a ratio of 64-bit int's after removing
- * common factors.
- */
-gnc_numeric gnc_numeric_mul(gnc_numeric a, gnc_numeric b,
- gint64 denom, gint how);
-
-/** Division. Note that division can overflow, in the following
- * sense: if we write x=a/b and y=c/d then x/y = (a*d)/(b*c)
- * If, after eliminating all common factors between the numerator
- * (a*d) and the denominator (b*c), then if either the numerator
- * and/or the denominator are *still* greater than 2^63, then
- * the division has overflowed.
- */
-gnc_numeric gnc_numeric_div(gnc_numeric x, gnc_numeric y,
- gint64 denom, gint how);
-/** Negate the argument */
-gnc_numeric gnc_numeric_neg(gnc_numeric a);
-
-/** Return the absolute value of the argument */
-gnc_numeric gnc_numeric_abs(gnc_numeric a);
-
-/**
- * Shortcut for common case: gnc_numeric_add(a, b, GNC_DENOM_AUTO,
- * GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER);
- */
-static inline
-gnc_numeric gnc_numeric_add_fixed(gnc_numeric a, gnc_numeric b) {
- return gnc_numeric_add(a, b, GNC_DENOM_AUTO,
- GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER);
-}
-
-/**
- * Shortcut for most common case: gnc_numeric_sub(a, b, GNC_DENOM_AUTO,
- * GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER);
- */
-static inline
-gnc_numeric gnc_numeric_sub_fixed(gnc_numeric a, gnc_numeric b) {
- return gnc_numeric_sub(a, b, GNC_DENOM_AUTO,
- GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER);
-}
-/** @} */
-
-/** @name Arithmetic Functions with Exact Error Returns
- @{
-*/
-/** The same as gnc_numeric_add, but uses 'error' for accumulating
- * conversion roundoff error. */
-gnc_numeric gnc_numeric_add_with_error(gnc_numeric a, gnc_numeric b,
- gint64 denom, gint how,
- gnc_numeric * error);
-
-/** The same as gnc_numeric_sub, but uses error for accumulating
- * conversion roundoff error. */
-gnc_numeric gnc_numeric_sub_with_error(gnc_numeric a, gnc_numeric b,
- gint64 denom, gint how,
- gnc_numeric * error);
-
-/** The same as gnc_numeric_mul, but uses error for
- * accumulating conversion roundoff error.
- */
-gnc_numeric gnc_numeric_mul_with_error(gnc_numeric a, gnc_numeric b,
- gint64 denom, gint how,
- gnc_numeric * error);
-
-/** The same as gnc_numeric_div, but uses error for
- * accumulating conversion roundoff error.
- */
-gnc_numeric gnc_numeric_div_with_error(gnc_numeric a, gnc_numeric b,
- gint64 denom, gint how,
- gnc_numeric * error);
-/** @} */
-
-/** @name Change Denominator
- @{
-*/
-/** Change the denominator of a gnc_numeric value to the
- * specified denominator under standard arguments
- * 'denom' and 'how'.
- */
-gnc_numeric gnc_numeric_convert(gnc_numeric in, gint64 denom,
- gint how);
-
-/** Same as gnc_numeric_convert, but return a remainder
- * value for accumulating conversion error.
-*/
-gnc_numeric gnc_numeric_convert_with_error(gnc_numeric in, gint64 denom,
- gint how,
- gnc_numeric * error);
-
-/** Return input after reducing it by Greated Common Factor (GCF)
- * elimination */
-gnc_numeric gnc_numeric_reduce(gnc_numeric in);
-/** @} */
-
-/** @name Deprecated, backwards-compatible definitions
- @{
-*/
-#define GNC_RND_FLOOR GNC_HOW_RND_FLOOR
-#define GNC_RND_CEIL GNC_HOW_RND_CEIL
-#define GNC_RND_TRUNC GNC_HOW_RND_TRUNC
-#define GNC_RND_PROMOTE GNC_HOW_RND_PROMOTE
-#define GNC_RND_ROUND_HALF_DOWN GNC_HOW_RND_ROUND_HALF_DOWN
-#define GNC_RND_ROUND_HALF_UP GNC_HOW_RND_ROUND_HALF_UP
-#define GNC_RND_ROUND GNC_HOW_RND_ROUND
-#define GNC_RND_NEVER GNC_HOW_RND_NEVER
-
-#define GNC_DENOM_EXACT GNC_HOW_DENOM_EXACT
-#define GNC_DENOM_REDUCE GNC_HOW_DENOM_REDUCE
-#define GNC_DENOM_LCD GNC_HOW_DENOM_LCD
-#define GNC_DENOM_FIXED GNC_HOW_DENOM_FIXED
-#define GNC_DENOM_SIGFIG GNC_HOW_DENOM_SIGFIG
-
-#define GNC_DENOM_SIGFIGS(X) GNC_HOW_DENOM_SIGFIGS(X)
-#define GNC_NUMERIC_GET_SIGFIGS(X) GNC_HOW_GET_SIGFIGS(X)
-/** @} */
-/** @} */
-#endif
Deleted: gnucash/trunk/src/engine/gnc-trace.c
===================================================================
--- gnucash/trunk/src/engine/gnc-trace.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/gnc-trace.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,370 +0,0 @@
-/* *****************************************************************\
- * gnc-trace.c -- QOF error logging and tracing facility *
- * Copyright (C) 1997-2003 Linas Vepstas <linas at linas.org> *
- * Copyright (c) 2005 Neil Williams <linux at codehelp.co.uk> *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
- * Author: Rob Clark (rclark at cs.hmc.edu) *
- * Author: Linas Vepstas (linas at linas.org) *
-\********************************************************************/
-
-/** @addtogroup Trace
-@{ */
-
-/** @file gnc-trace.c
- @brief QOF error logging facility
- @author Neil Williams <linux at codehelp.co.uk>
-*/
-
-#include "config.h"
-
-#include <glib.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#else
- /* What to do? */
-#endif
-#include <stdarg.h>
-#include <string.h>
-#include <sys/time.h>
-#include "qof.h"
-#include "gnc-trace.h"
-
-static FILE *fout = NULL;
-static gchar* filename = NULL;
-
-static const int MAX_TRACE_FILENAME = 100;
-static GHashTable *log_table = NULL;
-
-AS_STRING_FUNC(gncLogLevel, LOG_LEVEL_LIST) /**< enum_as_string function
-
-uses the enum_as_string macro from QOF
-but the From macro is not required. Lookups
-are done on the string. */
-
-FROM_STRING_FUNC(gncLogLevel, LOG_LEVEL_LIST)
-
-/* Don't be fooled: gnc_trace_num_spaces has external linkage and
- static storage, but can't be defined with 'extern' because it has
- an initializer, and can't be declared with 'static' because that
- would give it internal linkage. */
-gint __attribute__ ((unused)) gnc_trace_num_spaces = 0;
-
-static void
-fh_printer (const gchar *log_domain,
- GLogLevelFlags log_level,
- const gchar *message,
- gpointer user_data)
-{
- extern gint gnc_trace_num_spaces;
- FILE *fh = user_data;
- fprintf (fh, "%*s%s\n", gnc_trace_num_spaces, "", message);
- fflush(fh);
-}
-
-void
-gnc_log_init (void)
-{
- if(!fout) //allow gnc_set_logfile
- {
- fout = fopen ("/tmp/qof.trace", "w");
- }
-
- if(!fout && (filename = (char *)g_malloc(MAX_TRACE_FILENAME))) {
- snprintf(filename, MAX_TRACE_FILENAME-1, "/tmp/qof.trace.%d",
- getpid());
- fout = fopen (filename, "w");
- g_free(filename);
- }
-
- if(!fout)
- fout = stderr;
-
- g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK, fh_printer, fout);
-}
-
-/* Set the logging level of the given module. */
-void
-gnc_set_log_level(QofLogModule log_module, gncLogLevel level)
-{
- gchar* level_string;
-
- if(!log_module || level == 0) { return; }
- level_string = g_strdup(gncLogLevelasString(level));
- if(!log_table)
- {
- log_table = g_hash_table_new(g_str_hash, g_str_equal);
- }
- g_hash_table_insert(log_table, (gpointer)log_module, level_string);
-}
-
-static void
-log_module_foreach(gpointer key, gpointer value, gpointer data)
-{
- g_hash_table_insert(log_table, key, data);
-}
-
-/* Set the logging level for all known modules. */
-void
-gnc_set_log_level_global(gncLogLevel level)
-{
- gchar* level_string;
-
- if(!log_table || level == 0) { return; }
- level_string = g_strdup(gncLogLevelasString(level));
- g_hash_table_foreach(log_table, log_module_foreach, level_string);
-}
-
-void
-gnc_set_logfile (FILE *outfile)
-{
- if(!outfile) { fout = stderr; return; }
- fout = outfile;
-}
-
-void
-qof_log_init_filename (const gchar* logfilename)
-{
- if(!logfilename)
- {
- fout = stderr;
- }
- else
- {
- filename = g_strdup(logfilename);
- fout = fopen(filename, "w");
- }
- gnc_log_init();
-}
-
-void
-qof_log_shutdown (void)
-{
- if(fout && fout != stderr) { fclose(fout); }
- if(filename) { g_free(filename); }
- g_hash_table_destroy(log_table);
-}
-
-#define MAX_CHARS 50
-/* gnc_log_prettify() cleans up subroutine names. AIX/xlC has the habit
- * of printing signatures not names; clean this up. On other operating
- * systems, truncate name to 30 chars. Note this routine is not thread
- * safe. Note we wouldn't need this routine if AIX did something more
- * reasonable. Hope thread safety doesn't poke us in eye. */
-const char *
-gnc_log_prettify (const char *name)
-{
- static char bf[128];
- char *p;
-
- if (!name)
- return "";
-
- strncpy (bf, name, MAX_CHARS-1); bf[MAX_CHARS-2] = 0;
- p = strchr (bf, '(');
-
- if (p)
- {
- *(p+1) = ')';
- *(p+2) = 0x0;
- }
- else
- strcpy (&bf[MAX_CHARS-4], "...()");
-
- return bf;
-}
-
-/********************************************************************\
-\********************************************************************/
-
-#define NUM_CLOCKS 10
-
-static
-struct timeval gnc_clock[NUM_CLOCKS] = {
- {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
- {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
-};
-
-static
-struct timeval gnc_clock_total[NUM_CLOCKS] = {
- {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
- {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},
-};
-
-void
-gnc_start_clock (int clockno, QofLogModule log_module, gncLogLevel log_level,
- const char *function_name, const char *format, ...)
-{
- struct timezone tz;
- va_list ap;
-
- if ((0>clockno) || (NUM_CLOCKS <= clockno)) return;
- gettimeofday (&gnc_clock[clockno], &tz);
-
- if (!fout) gnc_log_init();
-
- fprintf (fout, "Clock %d Start: %s: ",
- clockno, gnc_log_prettify (function_name));
-
- va_start (ap, format);
-
- vfprintf (fout, format, ap);
-
- va_end (ap);
-
- fprintf (fout, "\n");
- fflush (fout);
-}
-
-void
-gnc_report_clock (int clockno, QofLogModule log_module, gncLogLevel log_level,
- const char *function_name, const char *format, ...)
-{
- struct timezone tz;
- struct timeval now;
- va_list ap;
-
- if ((0>clockno) || (NUM_CLOCKS <= clockno)) return;
- gettimeofday (&now, &tz);
-
- /* need to borrow to make difference */
- if (now.tv_usec < gnc_clock[clockno].tv_usec)
- {
- now.tv_sec --;
- now.tv_usec += 1000000;
- }
- now.tv_sec -= gnc_clock[clockno].tv_sec;
- now.tv_usec -= gnc_clock[clockno].tv_usec;
-
- gnc_clock_total[clockno].tv_sec += now.tv_sec;
- gnc_clock_total[clockno].tv_usec += now.tv_usec;
-
- if (!fout) gnc_log_init();
-
- fprintf (fout, "Clock %d Elapsed: %ld.%06lds %s: ",
- clockno, (long int) now.tv_sec, (long int) now.tv_usec,
- gnc_log_prettify (function_name));
-
- va_start (ap, format);
-
- vfprintf (fout, format, ap);
-
- va_end (ap);
-
- fprintf (fout, "\n");
- fflush (fout);
-}
-
-void
-gnc_report_clock_total (int clockno,
- QofLogModule log_module, gncLogLevel log_level,
- const char *function_name, const char *format, ...)
-{
- va_list ap;
-
- if ((0>clockno) || (NUM_CLOCKS <= clockno)) return;
-
- /* need to normalize usec */
- while (gnc_clock_total[clockno].tv_usec >= 1000000)
- {
- gnc_clock_total[clockno].tv_sec ++;
- gnc_clock_total[clockno].tv_usec -= 1000000;
- }
-
- if (!fout) gnc_log_init();
-
- fprintf (fout, "Clock %d Total Elapsed: %ld.%06lds %s: ",
- clockno,
- (long int) gnc_clock_total[clockno].tv_sec,
- (long int) gnc_clock_total[clockno].tv_usec,
- gnc_log_prettify (function_name));
-
- va_start (ap, format);
-
- vfprintf (fout, format, ap);
-
- va_end (ap);
-
- fprintf (fout, "\n");
- fflush (fout);
-}
-
-gboolean
-gnc_should_log(QofLogModule log_module, gncLogLevel log_level)
-{
- gchar* log_string;
- gncLogLevel maximum; /* Any log_level less than this will be logged. */
-
- log_string = NULL;
- if(!log_table || log_module == NULL || log_level == 0) { return FALSE; }
- log_string = (gchar*)g_hash_table_lookup(log_table, log_module);
- /* if log_module not found, do not log. */
- if(!log_string) { return FALSE; }
- maximum = gncLogLevelfromString(log_string);
- if(log_level <= maximum) { return TRUE; }
- return FALSE;
-}
-
-void qof_log_set_default(gncLogLevel log_level)
-{
- gnc_set_log_level(QOF_MOD_BACKEND, log_level);
- gnc_set_log_level(QOF_MOD_CLASS, log_level);
- gnc_set_log_level(QOF_MOD_ENGINE, log_level);
- gnc_set_log_level(QOF_MOD_OBJECT, log_level);
- gnc_set_log_level(QOF_MOD_KVP, log_level);
- gnc_set_log_level(QOF_MOD_MERGE, log_level);
- gnc_set_log_level(QOF_MOD_QUERY, log_level);
- gnc_set_log_level(QOF_MOD_SESSION, log_level);
-}
-
-struct hash_s
-{
- QofLogCB cb;
- gpointer data;
-};
-
-static void hash_cb (gpointer key, gpointer value, gpointer data)
-{
- struct hash_s *iter;
-
- iter = (struct hash_s*)data;
- if(!iter) { return; }
- (iter->cb)(key, value, iter->data);
-}
-
-void qof_log_module_foreach(QofLogCB cb, gpointer data)
-{
- struct hash_s iter;
-
- if(!cb) { return; }
- iter.cb = cb;
- iter.data = data;
- g_hash_table_foreach(log_table, hash_cb, (gpointer)&iter);
-}
-
-gint qof_log_module_count(void)
-{
- if(!log_table) { return 0; }
- return g_hash_table_size(log_table);
-}
-
-/** @} */
-
-/************************* END OF FILE ******************************\
-\********************************************************************/
Deleted: gnucash/trunk/src/engine/gnc-trace.h
===================================================================
--- gnucash/trunk/src/engine/gnc-trace.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/gnc-trace.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,274 +0,0 @@
-/********************************************************************\
- * gnc-trace.h -- QOF error logging and tracing facility *
- * Copyright (C) 1998-2003 Linas Vepstas <linas at linas.org> *
- * Copyright (c) 2005 Neil Williams <linux at codehelp.co.uk> *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
- * Author: Linas Vepstas (linas at linas.org) *
-\********************************************************************/
-
-/** @addtogroup Trace
- @{ */
-
-/** @file gnc-trace.h
- * @brief QOF error logging and tracing facility
- * @author Neil Williams <linux at codehelp.co.uk>
- */
-
-#ifndef GNC_TRACE_H
-#define GNC_TRACE_H
-
-#include <glib.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include "qof.h"
-#include "gnc-engine-util.h"
-
-#define QOF_MOD_ENGINE "qof-engine"
-
-#define LOG_LEVEL_LIST(_) \
- _(GNC_LOG_FATAL, = 0) \
- _(GNC_LOG_ERROR, = 1) \
- _(GNC_LOG_WARNING, = 2) \
- _(GNC_LOG_INFO, = 3) \
- _(GNC_LOG_DEBUG, = 4) \
- _(GNC_LOG_DETAIL, = 5) \
- _(GNC_LOG_TRACE, = 6)
-
-DEFINE_ENUM (gncLogLevel, LOG_LEVEL_LIST)
-
-/** Convert gncLogLevel to a string.
-
-The macro correlates the enum value and an
-exact copy as a string, removing the need to
-keep two separate lists in sync.
-*/
-AS_STRING_DEC(gncLogLevel, LOG_LEVEL_LIST)
-
-/** Convert the log_string to a gncLogLevel
-
-Only for use as a partner to ::gncLogLevelasString
-*/
-FROM_STRING_DEC(gncLogLevel, LOG_LEVEL_LIST)
-
-#define GNC_TRACE_INDENT_WIDTH 4
-
-/** Initialize the error logging subsystem
-
-\note Applications should call gnc_set_logfile
-to set the output, otherwise the
-default of \a /tmp/qof.trace will be used.
-
-As an alternative, use qof_log_init_filename
-which sets the filename and initialises the
-logging subsystem in one operation.
-*/
-void gnc_log_init (void);
-
-/** Set the logging level of the given log_module. */
-void gnc_set_log_level(QofLogModule module, gncLogLevel level);
-
-/** Set the logging level for all known log_modules.
-
-\note Unless a log_module has been registered using
-gnc_set_log_level, it will be unaffected by this change.
-
-*/
-void gnc_set_log_level_global(gncLogLevel level);
-
-/** Specify an alternate log output, to pipe or file. By default,
- * all logging goes to /tmp/qof.trace
-
- Needs to be called \b before gnc_log_init()
-*/
-void gnc_set_logfile (FILE *outfile);
-
-/** Specify a filename for log output.
-
-Calls gnc_log_init() for you.
-*/
-void qof_log_init_filename (const gchar* logfilename);
-
-/** Be nice, close the logfile is possible. */
-void qof_log_shutdown (void);
-
-/** gnc_log_prettify() cleans up subroutine names. AIX/xlC has the habit
- * of printing signatures not names; clean this up. On other operating
- * systems, truncate name to 30 chars. Note this routine is not thread
- * safe. Note we wouldn't need this routine if AIX did something more
- * reasonable. Hope thread safety doesn't poke us in eye. */
-const char * gnc_log_prettify (const char *name);
-
-/** Do not log log_modules that have not been enabled.
-
- Whether to log cannot be decided inline because a hashtable is
- now used. This is the price of extending logging to non-Gnucash
- log_modules.
-
-*/
-gboolean gnc_should_log(QofLogModule log_module, gncLogLevel log_level);
-
-/** Set the default QOF log_modules to the log level. */
-void qof_log_set_default(gncLogLevel log_level);
-
-typedef void (*QofLogCB) (QofLogModule log_module, gncLogLevel* log_level, gpointer user_data);
-
-/** Iterate over each known log_module
-
-Only log_modules with log_levels set will
-be available.
-*/
-void qof_log_module_foreach(QofLogCB cb, gpointer data);
-
-/** Number of log_modules registered*/
-gint qof_log_module_count(void);
-
-#define FUNK gnc_log_prettify(__FUNCTION__)
-
-/** Log error/waring/info messages to stderr or to other pipe.
- * This logging infrastructure is meant for validating the
- * correctness of the execution of the code. 'Info' level
- * messages help trace program flow. 'Error' messages are
- * meant to indicate internal data inconsistencies.
- *
- * Messages can be logged to stdout, stderr, or to any desired
- * FILE * file handle. Use fdopen() to get a file handle from a
- * file descriptor. Use gnc_set_logfile to set the logging file
- * handle.
- */
-
-/** Log an fatal error */
-#define FATAL(format, args...) do { \
- g_log (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, \
- "Fatal Error: %s(): " format, FUNK , ## args); \
-} while (0)
-
-/** Log an serious error */
-#define PERR(format, args...) do { \
- if (gnc_should_log (log_module, GNC_LOG_ERROR)) {\
- g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, \
- "Error: %s(): " format, FUNK , ## args); \
- } \
-} while (0)
-
-/** Log an warning */
-#define PWARN(format, args...) do { \
- if (gnc_should_log (log_module, GNC_LOG_WARNING)) { \
- g_log (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, \
- "Warning: %s(): " format, FUNK , ## args); \
- } \
-} while (0)
-
-/** Print an informational note */
-#define PINFO(format, args...) do { \
- if (gnc_should_log (log_module, GNC_LOG_INFO)) { \
- g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, \
- "Info: %s(): " format, \
- FUNK , ## args); \
- } \
-} while (0)
-
-/** Print an debugging message */
-#define DEBUG(format, args...) do { \
- if (gnc_should_log (log_module, GNC_LOG_DEBUG)) {\
- g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, \
- "Debug: %s(): " format, \
- FUNK , ## args); \
- } \
-} while (0)
-
-/** Print an function entry debugging message */
-#define ENTER(format, args...) do { \
- extern gint gnc_trace_num_spaces; \
- if (gnc_should_log (log_module, GNC_LOG_DEBUG)) {\
- g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, \
- "Enter in %s: %s()" format, __FILE__, \
- FUNK , ## args); \
- gnc_trace_num_spaces += GNC_TRACE_INDENT_WIDTH;\
- } \
-} while (0)
-
-/** Print an function exit debugging message */
-#define LEAVE(format, args...) do { \
- extern gint gnc_trace_num_spaces; \
- if (gnc_should_log (log_module, GNC_LOG_DEBUG)) {\
- gnc_trace_num_spaces -= GNC_TRACE_INDENT_WIDTH;\
- g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, \
- "Leave: %s()" format, \
- FUNK , ## args); \
- } \
-} while (0)
-
-/** Print an function trace debugging message */
-#define TRACE(format, args...) do { \
- if (gnc_should_log (log_module, GNC_LOG_TRACE)) {\
- g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, \
- "Trace: %s(): " format, FUNK , ## args); \
- } \
-} while (0)
-
-#define DEBUGCMD(x) do { \
- if (gnc_should_log (log_module, GNC_LOG_DEBUG)) { \
- (x); \
- } \
-} while (0)
-
-/* -------------------------------------------------------- */
-/** Infrastructure to make timing measurements for critical peices
- * of code. Used for only for performance tuning & debugging.
- */
-
-void gnc_start_clock (int clockno, QofLogModule log_module, gncLogLevel log_level,
- const char *function_name, const char *format, ...);
-
-void gnc_report_clock (int clockno,
- QofLogModule log_module,
- gncLogLevel log_level,
- const char *function_name,
- const char *format, ...);
-
-void gnc_report_clock_total (int clockno,
- QofLogModule log_module,
- gncLogLevel log_level,
- const char *function_name,
- const char *format, ...);
-
-/** start a particular timer */
-#define START_CLOCK(clockno,format, args...) do { \
- if (gnc_should_log (log_module, GNC_LOG_INFO)) \
- gnc_start_clock (clockno, log_module, GNC_LOG_INFO, \
- __FUNCTION__, format , ## args); \
-} while (0)
-
-/** report elapsed time since last report on a particular timer */
-#define REPORT_CLOCK(clockno,format, args...) do { \
- if (gnc_should_log (log_module, GNC_LOG_INFO)) \
- gnc_report_clock (clockno, log_module, GNC_LOG_INFO, \
- __FUNCTION__, format , ## args); \
-} while (0)
-
-/** report total elapsed time since timer started */
-#define REPORT_CLOCK_TOTAL(clockno,format, args...) do { \
- if (gnc_should_log (log_module, GNC_LOG_INFO)) \
- gnc_report_clock_total (clockno, log_module, GNC_LOG_INFO, \
- __FUNCTION__, format , ## args); \
-} while (0)
-
-#endif /* GNC_TRACE_H */
-/* @} */
Deleted: gnucash/trunk/src/engine/guid.c
===================================================================
--- gnucash/trunk/src/engine/guid.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/guid.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,681 +0,0 @@
-/********************************************************************\
- * guid.c -- globally unique ID implementation *
- * Copyright (C) 2000 Dave Peticolas <peticola at cs.ucdavis.edu> *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-#define _GNU_SOURCE
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-#include <ctype.h>
-#include <dirent.h>
-#include <glib.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/times.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "guid.h"
-#include "md5.h"
-#include "qofid.h"
-#include "gnc-trace.h"
-
-# ifndef P_tmpdir
-# define P_tmpdir "/tmp"
-# endif
-
-/** Constants *******************************************************/
-#define DEBUG_GUID 0
-#define BLOCKSIZE 4096
-#define THRESHOLD (2 * BLOCKSIZE)
-
-
-/** Static global variables *****************************************/
-static gboolean guid_initialized = FALSE;
-static struct md5_ctx guid_context;
-static GMemChunk *guid_memchunk = NULL;
-
-/* This static indicates the debugging module that this .o belongs to. */
-static QofLogModule log_module = QOF_MOD_ENGINE;
-
-/** Memory management routines ***************************************/
-static void
-guid_memchunk_init (void)
-{
- if (!guid_memchunk)
- guid_memchunk = g_mem_chunk_create (GUID, 512, G_ALLOC_AND_FREE);
-}
-
-static void
-guid_memchunk_shutdown (void)
-{
- if (guid_memchunk)
- {
- g_mem_chunk_destroy (guid_memchunk);
- guid_memchunk = NULL;
- }
-}
-
-GUID *
-guid_malloc (void)
-{
- if (!guid_memchunk) guid_memchunk_init();
- return g_chunk_new (GUID, guid_memchunk);
-}
-
-void
-guid_free (GUID *guid)
-{
- if (!guid)
- return;
-
- g_chunk_free (guid, guid_memchunk);
-}
-
-
-const GUID *
-guid_null(void)
-{
- static int null_inited = 0;
- static GUID null_guid;
-
- if (!null_inited)
- {
- int i;
- char *tmp = "NULLGUID.EMPTY.";
-
- /* 16th space for '\O' */
- for (i = 0; i < 16; i++)
- null_guid.data[i] = tmp[i];
-
- null_inited = 1;
- }
-
- return &null_guid;
-}
-
-/** Function implementations ****************************************/
-
-/* This code is based on code in md5.c in GNU textutils. */
-static size_t
-init_from_stream(FILE *stream, size_t max_size)
-{
- char buffer[BLOCKSIZE + 72];
- size_t sum, block_size, total;
-
- if (max_size <= 0)
- return 0;
-
- total = 0;
-
- /* Iterate over file contents. */
- while (1)
- {
- /* We read the file in blocks of BLOCKSIZE bytes. One call of the
- * computation function processes the whole buffer so that with the
- * next round of the loop another block can be read. */
- size_t n;
- sum = 0;
-
- if (max_size < BLOCKSIZE)
- block_size = max_size;
- else
- block_size = BLOCKSIZE;
-
- /* Read block. Take care for partial reads. */
- do
- {
- n = fread (buffer + sum, 1, block_size - sum, stream);
-
- sum += n;
- }
- while (sum < block_size && n != 0);
-
- max_size -= sum;
-
- if (n == 0 && ferror (stream))
- return total;
-
- /* If end of file or max_size is reached, end the loop. */
- if ((n == 0) || (max_size == 0))
- break;
-
- /* Process buffer with BLOCKSIZE bytes. Note that
- * BLOCKSIZE % 64 == 0 */
- md5_process_block (buffer, BLOCKSIZE, &guid_context);
-
- total += sum;
- }
-
- /* Add the last bytes if necessary. */
- if (sum > 0)
- {
- md5_process_bytes (buffer, sum, &guid_context);
- total += sum;
- }
-
- return total;
-}
-
-static size_t
-init_from_file(const char *filename, size_t max_size)
-{
- struct stat stats;
- size_t total = 0;
- size_t file_bytes;
- FILE *fp;
-
- memset(&stats, 0, sizeof(stats));
- if (stat(filename, &stats) != 0)
- return 0;
-
- md5_process_bytes(&stats, sizeof(stats), &guid_context);
- total += sizeof(stats);
-
- if (max_size <= 0)
- return total;
-
- fp = fopen (filename, "r");
- if (fp == NULL)
- return total;
-
- file_bytes = init_from_stream(fp, max_size);
-
- PINFO ("guid_init got %llu bytes from %s", (unsigned long long int) file_bytes,
- filename);
-
- total += file_bytes;
-
- fclose(fp);
-
- return total;
-}
-
-static size_t
-init_from_dir(const char *dirname, unsigned int max_files)
-{
- char filename[1024];
- struct dirent *de;
- struct stat stats;
- size_t total;
- int result;
- DIR *dir;
-
- if (max_files <= 0)
- return 0;
-
- dir = opendir (dirname);
- if (dir == NULL)
- return 0;
-
- total = 0;
-
- do
- {
- de = readdir(dir);
- if (de == NULL)
- break;
-
- md5_process_bytes(de, sizeof(struct dirent), &guid_context);
- total += sizeof(struct dirent);
-
- result = snprintf(filename, sizeof(filename),
- "%s/%s", dirname, de->d_name);
- if ((result < 0) || (result >= (int)sizeof(filename)))
- continue;
-
- memset(&stats, 0, sizeof(stats));
- if (stat(filename, &stats) != 0)
- continue;
- md5_process_bytes(&stats, sizeof(stats), &guid_context);
- total += sizeof(stats);
-
- max_files--;
- } while (max_files > 0);
-
- closedir(dir);
-
- return total;
-}
-
-static size_t
-init_from_time(void)
-{
- size_t total;
- time_t t_time;
- clock_t clocks;
- struct tms tms_buf;
-
- total = 0;
-
- t_time = time(NULL);
- md5_process_bytes(&t_time, sizeof(t_time), &guid_context);
- total += sizeof(t_time);
-
- clocks = times(&tms_buf);
- md5_process_bytes(&clocks, sizeof(clocks), &guid_context);
- md5_process_bytes(&tms_buf, sizeof(tms_buf), &guid_context);
- total += sizeof(clocks) + sizeof(tms_buf);
-
- return total;
-}
-
-static size_t
-init_from_int(int val)
-{
- md5_process_bytes(&val, sizeof(val), &guid_context);
- return sizeof(int);
-}
-
-static size_t
-init_from_buff(unsigned char * buf, size_t buflen)
-{
- md5_process_bytes(buf, buflen, &guid_context);
- return buflen;
-}
-
-void
-guid_init(void)
-{
- size_t bytes = 0;
-
- /* Not needed; taken care of on first malloc.
- * guid_memchunk_init(); */
-
- md5_init_ctx(&guid_context);
-
- /* entropy pool */
- bytes += init_from_file ("/dev/urandom", 512);
-
- /* files */
- {
- const char * files[] =
- { "/etc/passwd",
- "/proc/loadavg",
- "/proc/meminfo",
- "/proc/net/dev",
- "/proc/rtc",
- "/proc/self/environ",
- "/proc/self/stat",
- "/proc/stat",
- "/proc/uptime",
- NULL
- };
- int i;
-
- for (i = 0; files[i] != NULL; i++)
- bytes += init_from_file(files[i], BLOCKSIZE);
- }
-
- /* directories */
- {
- const char * dirname;
- const char * dirs[] =
- {
- "/proc",
- P_tmpdir,
- "/var/lock",
- "/var/log",
- "/var/mail",
- "/var/spool/mail",
- "/var/run",
- NULL
- };
- int i;
-
- for (i = 0; dirs[i] != NULL; i++)
- bytes += init_from_dir(dirs[i], 32);
-
- dirname = getenv("HOME");
- if (dirname != NULL)
- bytes += init_from_dir(dirname, 32);
- }
-
- /* process and parent ids */
- {
- pid_t pid;
-
- pid = getpid();
- md5_process_bytes(&pid, sizeof(pid), &guid_context);
- bytes += sizeof(pid);
-
- pid = getppid();
- md5_process_bytes(&pid, sizeof(pid), &guid_context);
- bytes += sizeof(pid);
- }
-
- /* user info */
- {
- uid_t uid;
- gid_t gid;
- char *s;
-
- s = getlogin();
- if (s != NULL)
- {
- md5_process_bytes(s, strlen(s), &guid_context);
- bytes += strlen(s);
- }
-
- uid = getuid();
- md5_process_bytes(&uid, sizeof(uid), &guid_context);
- bytes += sizeof(uid);
-
- gid = getgid();
- md5_process_bytes(&gid, sizeof(gid), &guid_context);
- bytes += sizeof(gid);
- }
-
- /* host info */
- {
- char string[1024];
-
- memset(string, 0, sizeof(string));
- gethostname(string, sizeof(string));
- md5_process_bytes(string, sizeof(string), &guid_context);
- bytes += sizeof(string);
- }
-
- /* plain old random */
- {
- int n, i;
-
- srand((unsigned int) time(NULL));
-
- for (i = 0; i < 32; i++)
- {
- n = rand();
-
- md5_process_bytes(&n, sizeof(n), &guid_context);
- bytes += sizeof(n);
- }
- }
-
- /* time in secs and clock ticks */
- bytes += init_from_time();
-
- PINFO ("got %llu bytes", (unsigned long long int) bytes);
-
- if (bytes < THRESHOLD)
- PWARN("only got %llu bytes.\n"
- "The identifiers might not be very random.\n",
- (unsigned long long int)bytes);
-
- guid_initialized = TRUE;
-}
-
-void
-guid_init_with_salt(const void *salt, size_t salt_len)
-{
- guid_init();
-
- md5_process_bytes(salt, salt_len, &guid_context);
-}
-
-void
-guid_init_only_salt(const void *salt, size_t salt_len)
-{
- md5_init_ctx(&guid_context);
-
- md5_process_bytes(salt, salt_len, &guid_context);
-
- guid_initialized = TRUE;
-}
-
-void
-guid_shutdown (void)
-{
- guid_memchunk_shutdown();
-}
-
-#define GUID_PERIOD 5000
-
-void
-guid_new(GUID *guid)
-{
- static int counter = 0;
- struct md5_ctx ctx;
-
- if (guid == NULL)
- return;
-
- if (!guid_initialized)
- guid_init();
-
- /* make the id */
- ctx = guid_context;
- md5_finish_ctx(&ctx, guid->data);
-
- /* update the global context */
- init_from_time();
-
- /* Make it a little extra salty. I think init_from_time was buggy,
- * or something, since duplicate id's actually happened. Or something
- * like that. I think this is because init_from_time kept returning
- * the same values too many times in a row. So we'll do some 'block
- * chaining', and feed in the old guid as new random data.
- *
- * Anyway, I think the whole fact that I saw a bunch of duplicate
- * id's at one point, but can't reproduce the bug is rather alarming.
- * Something must be broken somewhere, and merely adding more salt
- * is just hiding the problem, not fixing it.
- */
- init_from_int (433781*counter);
- init_from_buff (guid->data, 16);
-
- if (counter == 0)
- {
- FILE *fp;
-
- fp = fopen ("/dev/urandom", "r");
- if (fp == NULL)
- return;
-
- init_from_stream(fp, 32);
-
- fclose(fp);
-
- counter = GUID_PERIOD;
- }
-
- counter--;
-}
-
-GUID
-guid_new_return(void)
-{
- GUID guid;
-
- guid_new (&guid);
-
- return guid;
-}
-
-/* needs 32 bytes exactly, doesn't print a null char */
-static void
-encode_md5_data(const unsigned char *data, char *buffer)
-{
- size_t count;
-
- for (count = 0; count < 16; count++, buffer += 2)
- sprintf(buffer, "%02x", data[count]);
-}
-
-/* returns true if the first 32 bytes of buffer encode
- * a hex number. returns false otherwise. Decoded number
- * is packed into data in little endian order. */
-static gboolean
-decode_md5_string(const char *string, unsigned char *data)
-{
- unsigned char n1, n2;
- size_t count = -1;
- char c1, c2;
-
- if (NULL == data) return FALSE;
- if (NULL == string) goto badstring;
-
- for (count = 0; count < 16; count++)
- {
- /* check for a short string e.g. null string ... */
- if ((0==string[2*count]) || (0==string[2*count+1])) goto badstring;
-
- c1 = tolower(string[2 * count]);
- if (!isxdigit(c1)) goto badstring;
-
- c2 = tolower(string[2 * count + 1]);
- if (!isxdigit(c2)) goto badstring;
-
- if (isdigit(c1))
- n1 = c1 - '0';
- else
- n1 = c1 - 'a' + 10;
-
- if (isdigit(c2))
- n2 = c2 - '0';
- else
- n2 = c2 - 'a' + 10;
-
- data[count] = (n1 << 4) | n2;
- }
- return TRUE;
-
-badstring:
- for (count = 0; count < 16; count++)
- {
- data[count] = 0;
- }
- return FALSE;
-}
-
-/* Allocate the key */
-
-const char *
-guid_to_string(const GUID * guid)
-{
-#ifdef G_THREADS_ENABLED
- static GStaticPrivate guid_buffer_key = G_STATIC_PRIVATE_INIT;
- gchar *string;
-
- string = g_static_private_get (&guid_buffer_key);
- if (string == NULL) {
- string = malloc(GUID_ENCODING_LENGTH+1);
- g_static_private_set (&guid_buffer_key, string, g_free);
- }
-#else
- static char string[64];
-#endif
-
- encode_md5_data(guid->data, string);
- string[GUID_ENCODING_LENGTH] = '\0';
-
- return string;
-}
-
-char *
-guid_to_string_buff(const GUID * guid, char *string)
-{
- if (!string || !guid) return NULL;
-
- encode_md5_data(guid->data, string);
-
- string[GUID_ENCODING_LENGTH] = '\0';
- return &string[GUID_ENCODING_LENGTH];
-}
-
-gboolean
-string_to_guid(const char * string, GUID * guid)
-{
- return decode_md5_string(string, (guid != NULL) ? guid->data : NULL);
-}
-
-gboolean
-guid_equal(const GUID *guid_1, const GUID *guid_2)
-{
- if (guid_1 && guid_2)
- return (memcmp(guid_1, guid_2, sizeof(GUID)) == 0);
- else
- return FALSE;
-}
-
-gint
-guid_compare(const GUID *guid_1, const GUID *guid_2)
-{
- if (guid_1 == guid_2)
- return 0;
-
- /* nothing is always less than something */
- if (!guid_1 && guid_2)
- return -1;
-
- if (guid_1 && !guid_2)
- return 1;
-
- return memcmp (guid_1, guid_2, sizeof (GUID));
-}
-
-guint
-guid_hash_to_guint (gconstpointer ptr)
-{
- const GUID *guid = ptr;
-
- if (!guid)
- {
- PERR ("received NULL guid pointer.");
- return 0;
- }
-
- if (sizeof(guint) <= sizeof(guid->data))
- {
- return (*((guint *) guid->data));
- }
- else
- {
- guint hash = 0;
- unsigned int i, j;
-
- for (i = 0, j = 0; i < sizeof(guint); i++, j++) {
- if (j == 16) j = 0;
-
- hash <<= 4;
- hash |= guid->data[j];
- }
-
- return hash;
- }
-}
-
-static gint
-guid_g_hash_table_equal (gconstpointer guid_a, gconstpointer guid_b)
-{
- return guid_equal (guid_a, guid_b);
-}
-
-GHashTable *
-guid_hash_table_new (void)
-{
- return g_hash_table_new (guid_hash_to_guint, guid_g_hash_table_equal);
-}
Deleted: gnucash/trunk/src/engine/guid.h
===================================================================
--- gnucash/trunk/src/engine/guid.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/guid.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,204 +0,0 @@
-/********************************************************************\
- * guid.h -- globally unique ID User API *
- * Copyright (C) 2000 Dave Peticolas <peticola at cs.ucdavis.edu> *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-#ifndef GUID_H
-#define GUID_H
-
-#include <glib.h>
-#include <stddef.h>
-
-/** @addtogroup Entity
- @{ */
-/** @addtogroup GUID
- Globally Unique ID's provide a way to uniquely identify
- some thing. A GUID is a unique, cryptographically
- random 128-bit value. The identifier is so random that
- it is safe to assume that there is no other such item
- on the planet Earth, and indeed, not even in the Galaxy
- or beyond.
-
- QOF GUID's can be used independently of any other subsystem
- in QOF. In particular, they do not require the use of
- other parts of the object subsystem.
-
- @{ */
-/** @file guid.h
- @brief globally unique ID User API
- @author Copyright (C) 2000 Dave Peticolas <peticola at cs.ucdavis.edu>
-*/
-
-/** The type used to store guids */
-typedef union _GUID
-{
- unsigned char data[16];
-
- int __align_me; /* this just ensures that GUIDs are 32-bit
- * aligned on systems that need them to be. */
-} GUID;
-
-
-/** number of characters needed to encode a guid as a string
- * not including the null terminator. */
-#define GUID_ENCODING_LENGTH 32
-
-
-/** Initialize the id generator with a variety of random
- * sources.
- *
- * @note Only one of guid_init(), guid_init_with_salt() and
- * guid_init_only_salt() should be called. Calling any
- * initialization function a second time will reset the generator and
- * erase the effect of the first call.
- */
-void guid_init(void);
-
-/** Initialize the id generator with a variety of random sources. and
- * with the data given in the salt argument. This argument can be
- * used to add additional randomness to the generated ids.
- *
- * @param salt The additional random values to add to the generator.
- *
- * @param salt_len The length of the additional random values.
- *
- * @note Only one of guid_init(), guid_init_with_salt() and
- * guid_init_only_salt() should be called. Calling any
- * initialization function a second time will reset the generator and
- * erase the effect of the first call.
- */
-void guid_init_with_salt(const void *salt, size_t salt_len);
-
-/** Initialize the id generator with the data given in the salt
- * argument, but not with any other source. Calling this function with
- * a specific argument will reliably produce a specific sequence of
- * ids.
- *
- * @param salt The additional random values to add to the generator.
- *
- * @param salt_len The length of the additional random values.
- *
- * @note Only one of guid_init(), guid_init_with_salt() and
- * guid_init_only_salt() should be called. Calling any
- * initialization function a second time will reset the generator and
- * erase the effect of the first call.
- */
-void guid_init_only_salt(const void *salt, size_t salt_len);
-
-/** Release the memory chunk associated with gui storage. Use this
- * only when shutting down the program, as it invalidates *all*
- * GUIDs at once. */
-void guid_shutdown (void);
-
-/** Generate a new id. If no initialization function has been called,
- * guid_init() will be called before the id is created.
- *
- * @param guid A pointer to an existing guid data structure. The
- * existing value will be replaced with a new value.
- *
- * This routine uses the md5 algorithm to build strong random guids.
- * Note that while guid's are generated randomly, the odds of this
- * routine returning a non-unique id are astronomically small.
- * (Literally astronomically: If you had Cray's on every solar
- * system in the universe running for the entire age of the universe,
- * you'd still have less than a one-in-a-million chance of coming up
- * with a duplicate id. 2^128 == 10^38 is a really really big number.)
- */
-void guid_new(GUID *guid);
-
-/** Generate a new id. If no initialization function has been called,
- * guid_init() will be called before the id is created.
- *
- * @return guid A pointer to a data structure containing a new GUID.
- * The memory pointed to is owned by this routine and the guid must
- * be copied out.
- *
- * CAS: huh? make that: @return guid A data structure containing a newly
- * allocated GUID. Caller is responsible for calling guid_free().
- */
-GUID guid_new_return(void);
-
-/** Returns a GUID which is guaranteed to never reference any entity. */
-/* CAS: AFAICT: this isn't really guaranteed, but it's only as likely
- as any other md5 collision. This could be guaranteed if GUID
- contained a validity flag. */
-const GUID * guid_null (void);
-
-/** Efficiently allocate & free memory for GUIDs */
-GUID * guid_malloc (void);
-
-/* Return a guid set to all zero's */
-void guid_free (GUID *guid);
-
-/** The guid_to_string() routine returns a null-terminated string
- * encoding of the id. String encodings of identifiers are hex
- * numbers printed only with the characters '0' through '9' and
- * 'a' through 'f'. The encoding will always be GUID_ENCODING_LENGTH
- * characters long.
- *
- * XXX This routine is not thread safe and is deprecated. Please
- * use the routine guid_to_string_buff() instead.
- *
- * @param guid The guid to print.
- *
- * @return A pointer to the starting character of the string. The
- * returned memory is owned by this routine and may not be freed by
- * the caller.
- */
-const char * guid_to_string (const GUID * guid);
-
-/** The guid_to_string_buff() routine puts a null-terminated string
- * encoding of the id into the memory pointed at by buff. The
- * buffer must be at least GUID_ENCODING_LENGTH+1 characters long.
- * This routine is handy for avoiding a malloc/free cycle. It
- * returns a pointer to the >>end<< of what was written. (i.e. it
- * can be used like 'stpcpy' during string concatenation)
- *
- * @param guid The guid to print.
- *
- * @param buff The buffer to print it into.
- *
- * @return A pointer to the terminating null character of the string.
- */
-char * guid_to_string_buff (const GUID * guid, char *buff);
-
-
-/** Given a string, decode the id into the guid if guid is non-NULL.
- * The function returns TRUE if the string was a valid 32 character
- * hexadecimal number. This function accepts both upper and lower case
- * hex digits. If the return value is FALSE, the effect on guid is
- * undefined. */
-gboolean string_to_guid(const char * string, GUID * guid);
-
-
-/** Given two GUIDs, return TRUE if they are non-NULL and equal.
- * Return FALSE, otherwise. */
-gboolean guid_equal(const GUID *guid_1, const GUID *guid_2);
-gint guid_compare(const GUID *g1, const GUID *g2);
-
-/** Given a GUID *, hash it to a guint */
-guint guid_hash_to_guint(gconstpointer ptr);
-
-GHashTable *guid_hash_table_new(void);
-
-/* @} */
-/* @} */
-#endif
Deleted: gnucash/trunk/src/engine/kvp-util-p.h
===================================================================
--- gnucash/trunk/src/engine/kvp-util-p.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/kvp-util-p.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,108 +0,0 @@
-/********************************************************************\
- * kvp-util-p.h -- misc odd-job kvp utils (private file) *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-#ifndef XACC_KVP_UTIL_P_H
-#define XACC_KVP_UTIL_P_H
-
-#include "config.h"
-
-#include "guid.h"
-#include "kvp_frame.h"
-
-/** @addtogroup KVP
- @{
-*/
-/** @file kvp-util-p.h
- * @brief misc odd-job kvp utils engine-private routines
- * @author Copyright (C) 2001, 2003 Linas Vepstas <linas at linas.org> *
-*/
-/** @name KvpBag Bags of GUID Pointers
- @{
-*/
-
-/** The gnc_kvp_bag_add() routine is used to maintain a collection
- * of pointers in a kvp tree.
- *
- * The thing being pointed at is uniquely identified by its GUID.
- * This routine is typically used to create a linked list, and/or
- * a collection of pointers to objects that are 'related' to each
- * other in some way.
- *
- * The var-args should be pairs of strings (const char *) followed by
- * the corresponding GUID pointer (const GUID *). Terminate the varargs
- * with a NULL as the last string argument.
- *
- * The actual 'pointer' is stored in a subdirectory in a bag located at
- * the node directory 'path'. A 'bag' is merely a collection of
- * (unamed) values. The name of our bag is 'path'. A bag can contain
- * any kind of values, including frames. This routine will create a
- * frame, and put it in the bag. The frame will contain named data
- * from the subroutine arguments. Thus, for example:
- *
- * gnc_kvp_array (kvp, "foo", secs, "acct_guid", aguid,
- * "book_guid", bguid, NULL);
- *
- * will create a frame containing "/acct_guid" and "/book_guid", whose
- * values are aguid and bguid respecitvely. The frame will also
- * contain "/date", whose value will be secs. This frame will be
- * placed into the bag located at "foo".
- *
- * This routine returns a pointer to the frame that was created, or
- * NULL if an error occured.
- */
-
-KvpFrame * gnc_kvp_bag_add (KvpFrame *kvp_root, const char *path, time_t secs,
- const char *first_name, ...);
-
-
-/** The gnc_kvp_bag_merge() routine will move the bag contents from
- * the 'kvp_from', to the 'into' bag. It will then delete the
- * 'from' bag from the kvp tree.
- */
-void gnc_kvp_bag_merge (KvpFrame *kvp_into, const char *intopath,
- KvpFrame *kvp_from, const char *frompath);
-
-/** The gnc_kvp_bag_find_by_guid() routine examines the bag pointed
- * located at root. It looks for a frame in that bag that has the
- * guid value of "desired_guid" filed under the key name "guid_name".
- * If it finds that matching guid, then it returns a pointer to
- * the KVP frame that contains it. If it is not found, or if there
- * is any other error, NULL is returned.
- */
-
-KvpFrame * gnc_kvp_bag_find_by_guid (KvpFrame *root, const char * path,
- const char *guid_name, GUID *desired_guid);
-
-
-/** Remove the given frame from the bag. The frame is removed,
- * however, it is not deleted. Note that the frame pointer must
- * be a pointer to the actual frame (for example, as returned by
- * gnc_kvp_bag_find_by_guid() for by gnc_kvp_bag_add()), and not
- * some copy of the frame.
- */
-
-void gnc_kvp_bag_remove_frame (KvpFrame *root, const char *path,
- KvpFrame *fr);
-
-/** @} */
-/** @} */
-#endif /* XACC_KVP_UTIL_P_H */
Deleted: gnucash/trunk/src/engine/kvp-util.c
===================================================================
--- gnucash/trunk/src/engine/kvp-util.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/kvp-util.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,235 +0,0 @@
-/********************************************************************\
- * kvp_util.c -- misc odd-job kvp utils *
- * Copyright (C) 2001 Linas Vepstas <linas at linas.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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-#include "config.h"
-
-#include <glib.h>
-#include <stdio.h>
-
-#include "kvp_frame.h"
-#include "kvp-util.h"
-#include "kvp-util-p.h"
-
-/* ================================================================ */
-
-static KvpFrame *
-gnc_kvp_array_va (KvpFrame *kvp_root, const char * path,
- time_t secs, const char * first_name, va_list ap)
-{
- KvpFrame *cwd;
- Timespec ts;
- const char *name;
-
- if (!kvp_root) return NULL;
- if (!first_name) return NULL;
-
- /* Create subdirectory and put the actual data */
- cwd = kvp_frame_new();
-
- /* Record the time */
- ts.tv_sec = secs;
- ts.tv_nsec = 0;
- kvp_frame_set_timespec (cwd, "date", ts);
-
- /* Loop over the args */
- name = first_name;
- while (name)
- {
- const GUID *guid;
- guid = va_arg (ap, const GUID *);
-
- kvp_frame_set_guid (cwd, name, guid);
-
- name = va_arg (ap, const char *);
- }
-
- /* Attach cwd into the array */
- kvp_frame_add_frame_nc (kvp_root, path, cwd);
- return cwd;
-}
-
-/* ================================================================ */
-
-KvpFrame *
-gnc_kvp_bag_add (KvpFrame *pwd, const char * path,
- time_t secs, const char *first_name, ...)
-{
- KvpFrame *cwd;
- va_list ap;
- va_start (ap, first_name);
- cwd = gnc_kvp_array_va (pwd, path, secs, first_name, ap);
- va_end (ap);
- return cwd;
-}
-
-/* ================================================================ */
-
-#define MATCH_GUID(elt) { \
- KvpFrame *fr = kvp_value_get_frame (elt); \
- if (fr) { \
- GUID *guid = kvp_frame_get_guid (fr, guid_name); \
- if (guid && guid_equal (desired_guid, guid)) return fr; \
- } \
-}
-
-KvpFrame *
-gnc_kvp_bag_find_by_guid (KvpFrame *root, const char * path,
- const char *guid_name, GUID *desired_guid)
-{
- KvpValue *arr;
- KvpValueType valtype;
- GList *node;
-
- arr = kvp_frame_get_value (root, path);
- valtype = kvp_value_get_type (arr);
- if (KVP_TYPE_FRAME == valtype)
- {
- MATCH_GUID (arr);
- return NULL;
- }
-
- /* Its gotta be a single isolated frame, or a list of them. */
- if (KVP_TYPE_GLIST != valtype) return NULL;
-
- for (node = kvp_value_get_glist(arr); node; node=node->next)
- {
- KvpValue *va = node->data;
- MATCH_GUID (va);
- }
- return NULL;
-}
-
-/* ================================================================ */
-
-void
-gnc_kvp_bag_remove_frame (KvpFrame *root, const char *path, KvpFrame *fr)
-{
- KvpValue *arr;
- KvpValueType valtype;
- GList *node, *listhead;
-
- arr = kvp_frame_get_value (root, path);
- valtype = kvp_value_get_type (arr);
- if (KVP_TYPE_FRAME == valtype)
- {
- if (fr == kvp_value_get_frame (arr))
- {
- KvpValue *old_val = kvp_frame_replace_value_nc (root, path, NULL);
- kvp_value_replace_frame_nc (old_val, NULL);
- kvp_value_delete (old_val);
- }
- return;
- }
-
- /* Its gotta be a single isolated frame, or a list of them. */
- if (KVP_TYPE_GLIST != valtype) return;
-
- listhead = kvp_value_get_glist(arr);
- for (node = listhead; node; node=node->next)
- {
- KvpValue *va = node->data;
- if (fr == kvp_value_get_frame (va))
- {
- listhead = g_list_remove_link (listhead, node);
- g_list_free_1 (node);
- kvp_value_replace_glist_nc (arr, listhead);
- kvp_value_replace_frame_nc (va, NULL);
- kvp_value_delete (va);
- return;
- }
- }
-}
-
-/* ================================================================ */
-
-static KvpFrame *
-gnc_kvp_bag_get_first (KvpFrame *root, const char * path)
-{
- KvpValue *arr, *va;
- KvpValueType valtype;
- GList *node;
-
- arr = kvp_frame_get_value (root, path);
- valtype = kvp_value_get_type (arr);
- if (KVP_TYPE_FRAME == valtype)
- {
- return kvp_value_get_frame(arr);
- }
-
- /* Its gotta be a single isolated frame, or a list of them. */
- if (KVP_TYPE_GLIST != valtype) return NULL;
-
- node = kvp_value_get_glist(arr);
- if (NULL == node) return NULL;
-
- va = node->data;
- return kvp_value_get_frame(va);
-}
-
-void
-gnc_kvp_bag_merge (KvpFrame *kvp_into, const char *intopath,
- KvpFrame *kvp_from, const char *frompath)
-{
- KvpFrame *fr;
-
- fr = gnc_kvp_bag_get_first (kvp_from, frompath);
- while (fr)
- {
- gnc_kvp_bag_remove_frame (kvp_from, frompath, fr);
- kvp_frame_add_frame_nc (kvp_into, intopath, fr);
- fr = gnc_kvp_bag_get_first (kvp_from, frompath);
- }
-}
-
-/* ================================================================ */
-/*
- * See header for docs.
- */
-
-static void
-kv_pair_helper(gpointer key, gpointer val, gpointer user_data)
-{
- GSList **result = (GSList **) user_data;
- GHashTableKVPair *kvp = g_new(GHashTableKVPair, 1);
-
- kvp->key = key;
- kvp->value = val;
- *result = g_slist_prepend(*result, kvp);
-}
-
-GSList *
-g_hash_table_key_value_pairs(GHashTable *table)
-{
- GSList *result_list = NULL;
- g_hash_table_foreach(table, kv_pair_helper, &result_list);
- return result_list;
-}
-
-void
-g_hash_table_kv_pair_free_gfunc(gpointer data, gpointer user_data)
-{
- GHashTableKVPair *kvp = (GHashTableKVPair *) data;
- g_free(kvp);
-}
-
-/*======================== END OF FILE =============================*/
Deleted: gnucash/trunk/src/engine/kvp-util.h
===================================================================
--- gnucash/trunk/src/engine/kvp-util.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/kvp-util.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,64 +0,0 @@
-/********************************************************************\
- * kvp-util.h -- misc KVP utilities *
- * Copyright (C) 2003 Linas Vepstas <linas at linas.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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
-\********************************************************************/
-
-/** @addtogroup KVP
- @{
-*/
-/** @file kvp-util.h
- @brief GnuCash KVP utility functions
- */
-/** @name Hash Utilities
- @{
-*/
-
-#ifndef GNC_KVP_UTIL_H
-#define GNC_KVP_UTIL_H
-
-#include "config.h"
-
-typedef struct {
- gpointer key;
- gpointer value;
-} GHashTableKVPair;
-
-/**
- Returns a GSList* of all the
- keys and values in a given hash table. Data elements of lists are
- actual hash elements, so be careful, and deallocation of the
- GHashTableKVPairs in the result list are the caller's
- responsibility. A typical sequence might look like this:
-
- GSList *kvps = g_hash_table_key_value_pairs(hash);
- ... use kvps->data->key and kvps->data->val, etc. here ...
- g_slist_foreach(kvps, g_hash_table_kv_pair_free_gfunc, NULL);
- g_slist_free(kvps);
-
-*/
-
-GSList *g_hash_table_key_value_pairs(GHashTable *table);
-void g_hash_table_kv_pair_free_gfunc(gpointer data, gpointer user_data);
-
-/***********************************************************************/
-
-/** @} */
-/** @} */
-#endif /* GNC_KVP_UTIL_H */
Deleted: gnucash/trunk/src/engine/kvp_frame.c
===================================================================
--- gnucash/trunk/src/engine/kvp_frame.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/kvp_frame.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,1840 +0,0 @@
-/********************************************************************
- * kvp_frame.c -- Implements a key-value frame system *
- * Copyright (C) 2000 Bill Gribble *
- * Copyright (C) 2001,2003 Linas Vepstas <linas at linas.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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
- ********************************************************************/
-
-#include "config.h"
-
-#define _GNU_SOURCE
-#include <glib.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-
-#include "gnc-date.h"
-#include "gnc-trace.h"
-#include "gnc-engine-util.h"
-#include "gnc-numeric.h"
-#include "guid.h"
-#include "kvp_frame.h"
-
-
- /* Note that we keep the keys for this hash table in a GCache
- * (gnc_string_cache), as it is very likely we will see the
- * same keys over and over again */
-
-/* TODO: set the cache handling functions with hash_table_new_full */
-
-struct _KvpFrame
-{
- GHashTable * hash;
-};
-
-
-typedef struct
-{
- void *data;
- int datasize;
-} KvpValueBinaryData;
-
-struct _KvpValue
-{
- KvpValueType type;
- union {
- gint64 int64;
- double dbl;
- gnc_numeric numeric;
- gchar *str;
- GUID *guid;
- Timespec timespec;
- KvpValueBinaryData binary;
- GList *list;
- KvpFrame *frame;
- } value;
-};
-
-/* This static indicates the debugging module that this .o belongs to. */
-static QofLogModule log_module = QOF_MOD_KVP;
-
-/********************************************************************
- * KvpFrame functions
- ********************************************************************/
-
-static guint
-kvp_hash_func(gconstpointer v)
-{
- return g_str_hash(v);
-}
-
-static gint
-kvp_comp_func(gconstpointer v, gconstpointer v2)
-{
- return g_str_equal(v, v2);
-}
-
-static gboolean
-init_frame_body_if_needed(KvpFrame *f)
-{
- if(!f->hash)
- {
- f->hash = g_hash_table_new(&kvp_hash_func, &kvp_comp_func);
- }
- return(f->hash != NULL);
-}
-
-KvpFrame *
-kvp_frame_new(void)
-{
- KvpFrame * retval = g_new0(KvpFrame, 1);
-
- /* Save space until the frame is actually used */
- retval->hash = NULL;
- return retval;
-}
-
-static void
-kvp_frame_delete_worker(gpointer key, gpointer value, gpointer user_data)
-{
- gnc_string_cache_remove(key);
- kvp_value_delete((KvpValue *)value);
-}
-
-void
-kvp_frame_delete(KvpFrame * frame)
-{
- if (!frame) return;
-
- if(frame->hash)
- {
- /* free any allocated resource for frame or its children */
- g_hash_table_foreach(frame->hash, & kvp_frame_delete_worker,
- (gpointer)frame);
-
- /* delete the hash table */
- g_hash_table_destroy(frame->hash);
- frame->hash = NULL;
- }
- g_free(frame);
-}
-
-gboolean
-kvp_frame_is_empty(KvpFrame * frame)
-{
- if (!frame) return TRUE;
- if (!frame->hash) return TRUE;
- return FALSE;
-}
-
-static void
-kvp_frame_copy_worker(gpointer key, gpointer value, gpointer user_data)
-{
- KvpFrame * dest = (KvpFrame *)user_data;
- g_hash_table_insert(dest->hash,
- gnc_string_cache_insert(key),
- (gpointer)kvp_value_copy(value));
-}
-
-KvpFrame *
-kvp_frame_copy(const KvpFrame * frame)
-{
- KvpFrame * retval = kvp_frame_new();
-
- if (!frame) return retval;
-
- if(frame->hash)
- {
- if(!init_frame_body_if_needed(retval)) return(NULL);
- g_hash_table_foreach(frame->hash,
- & kvp_frame_copy_worker,
- (gpointer)retval);
- }
- return retval;
-}
-
-/* Replace the old value with the new value. Return the old value.
- * Passing in a null value into this routine has the effect of
- * removing the key from the KVP tree.
- */
-KvpValue *
-kvp_frame_replace_slot_nc (KvpFrame * frame, const char * slot,
- KvpValue * new_value)
-{
- gpointer orig_key;
- gpointer orig_value = NULL;
- int key_exists;
-
- if (!frame || !slot) return NULL;
- if (!init_frame_body_if_needed(frame)) return NULL; /* Error ... */
-
- key_exists = g_hash_table_lookup_extended(frame->hash, slot,
- & orig_key, & orig_value);
- if(key_exists)
- {
- g_hash_table_remove(frame->hash, slot);
- gnc_string_cache_remove(orig_key);
- }
- else
- {
- orig_value = NULL;
- }
-
- if(new_value)
- {
- g_hash_table_insert(frame->hash,
- gnc_string_cache_insert((gpointer) slot),
- new_value);
- }
-
- return (KvpValue *) orig_value;
-}
-
-/* Passing in a null value into this routine has the effect
- * of deleting the old value stored at this slot.
- */
-static inline void
-kvp_frame_set_slot_destructively(KvpFrame * frame, const char * slot,
- KvpValue * new_value)
-{
- KvpValue * old_value;
- old_value = kvp_frame_replace_slot_nc (frame, slot, new_value);
- kvp_value_delete (old_value);
-}
-
-/* ============================================================ */
-/* Get the named frame, or create it if it doesn't exist.
- * gcc -O3 should inline it. It performs no error checks,
- * the caller is responsible of passing good keys and frames.
- */
-static inline KvpFrame *
-get_or_make (KvpFrame *fr, const char * key)
-{
- KvpFrame *next_frame;
- KvpValue *value;
-
- value = kvp_frame_get_slot (fr, key);
- if (value)
- {
- next_frame = kvp_value_get_frame (value);
- }
- else
- {
- next_frame = kvp_frame_new ();
- kvp_frame_set_slot_nc (fr, key,
- kvp_value_new_frame_nc (next_frame));
- }
- return next_frame;
-}
-
-/* Get pointer to last frame in path. If teh path doesn't exist,
- * it is created. The string stored in keypath will be hopelessly
- * mangled .
- */
-static inline KvpFrame *
-kvp_frame_get_frame_slash_trash (KvpFrame *frame, char *key_path)
-{
- char *key, *next;
- if (!frame || !key_path) return frame;
-
- key = key_path;
- key --;
-
- while (key)
- {
- key ++;
- while ('/' == *key) { key++; }
- if (0x0 == *key) break; /* trailing slash */
- next = strchr (key, '/');
- if (next) *next = 0x0;
-
- frame = get_or_make (frame, key);
- if (!frame) break; /* error - should never happen */
-
- key = next;
- }
- return frame;
-}
-
-/* ============================================================ */
-/* Get pointer to last frame in path, or NULL if the path doesn't
- * exist. The string stored in keypath will be hopelessly mangled .
- */
-static inline const KvpFrame *
-kvp_frame_get_frame_or_null_slash_trash (const KvpFrame *frame, char *key_path)
-{
- KvpValue *value;
- char *key, *next;
- if (!frame || !key_path) return NULL;
-
- key = key_path;
- key --;
-
- while (key)
- {
- key ++;
- while ('/' == *key) { key++; }
- if (0x0 == *key) break; /* trailing slash */
- next = strchr (key, '/');
- if (next) *next = 0x0;
-
- value = kvp_frame_get_slot (frame, key);
- if (!value) return NULL;
- frame = kvp_value_get_frame (value);
- if (!frame) return NULL;
-
- key = next;
- }
- return frame;
-}
-
-/* Return pointer to last frame in path, and also store the
- * last dangling part of path in 'end_key'. If path doesn't
- * exist, it is created.
- */
-
-static inline KvpFrame *
-get_trailer_make (KvpFrame * frame, const char * key_path, const char **end_key)
-{
- const char *last_key;
-
- if (!frame || !key_path || (0 == key_path[0])) return NULL;
-
- last_key = strrchr (key_path, '/');
- if (NULL == last_key)
- {
- last_key = key_path;
- }
- else if (last_key == key_path)
- {
- last_key ++;
- }
- else if (0 == last_key[1])
- {
- return NULL;
- }
- else
- {
- char *root, *lkey;
- root = g_strdup (key_path);
- lkey = strrchr (root, '/');
- *lkey = 0;
- frame = kvp_frame_get_frame_slash_trash (frame, root);
- g_free(root);
-
- last_key ++;
- }
-
- *end_key = last_key;
- return frame;
-}
-
-
-/* Return pointer to last frame in path, or NULL if the path
- * doesn't exist. Also store the last dangling part of path
- * in 'end_key'.
- */
-
-static inline const KvpFrame *
-get_trailer_or_null (const KvpFrame * frame, const char * key_path, const char **end_key)
-{
- const char *last_key;
-
- if (!frame || !key_path || (0 == key_path[0])) return NULL;
-
- last_key = strrchr (key_path, '/');
- if (NULL == last_key)
- {
- last_key = key_path;
- }
- else if (last_key == key_path)
- {
- last_key ++;
- }
- else if (0 == last_key[1])
- {
- return NULL;
- }
- else
- {
- char *root, *lkey;
- root = g_strdup (key_path);
- lkey = strrchr (root, '/');
- *lkey = 0;
- frame = kvp_frame_get_frame_or_null_slash_trash (frame, root);
- g_free(root);
-
- last_key ++;
- }
-
- *end_key = last_key;
- return frame;
-}
-
-/* ============================================================ */
-
-void
-kvp_frame_set_gint64(KvpFrame * frame, const char * path, gint64 ival)
-{
- KvpValue *value;
- value = kvp_value_new_gint64 (ival);
- frame = kvp_frame_set_value_nc (frame, path, value);
- if (!frame) kvp_value_delete (value);
-}
-
-void
-kvp_frame_set_double(KvpFrame * frame, const char * path, double dval)
-{
- KvpValue *value;
- value = kvp_value_new_double (dval);
- frame = kvp_frame_set_value_nc (frame, path, value);
- if (!frame) kvp_value_delete (value);
-}
-
-void
-kvp_frame_set_numeric(KvpFrame * frame, const char * path, gnc_numeric nval)
-{
- KvpValue *value;
- value = kvp_value_new_gnc_numeric (nval);
- frame = kvp_frame_set_value_nc (frame, path, value);
- if (!frame) kvp_value_delete (value);
-}
-
-void
-kvp_frame_set_string(KvpFrame * frame, const char * path, const char* str)
-{
- KvpValue *value;
- value = kvp_value_new_string (str);
- frame = kvp_frame_set_value_nc (frame, path, value);
- if (!frame) kvp_value_delete (value);
-}
-
-void
-kvp_frame_set_guid(KvpFrame * frame, const char * path, const GUID *guid)
-{
- KvpValue *value;
- value = kvp_value_new_guid (guid);
- frame = kvp_frame_set_value_nc (frame, path, value);
- if (!frame) kvp_value_delete (value);
-}
-
-void
-kvp_frame_set_timespec(KvpFrame * frame, const char * path, Timespec ts)
-{
- KvpValue *value;
- value = kvp_value_new_timespec (ts);
- frame = kvp_frame_set_value_nc (frame, path, value);
- if (!frame) kvp_value_delete (value);
-}
-
-void
-kvp_frame_set_frame(KvpFrame * frame, const char * path, KvpFrame *fr)
-{
- KvpValue *value;
- value = kvp_value_new_frame (fr);
- frame = kvp_frame_set_value_nc (frame, path, value);
- if (!frame) kvp_value_delete (value);
-}
-
-void
-kvp_frame_set_frame_nc(KvpFrame * frame, const char * path, KvpFrame *fr)
-{
- KvpValue *value;
- value = kvp_value_new_frame_nc (fr);
- frame = kvp_frame_set_value_nc (frame, path, value);
- if (!frame) kvp_value_delete (value);
-}
-
-/* ============================================================ */
-
-KvpFrame *
-kvp_frame_set_value_nc (KvpFrame * frame, const char * key_path,
- KvpValue * value)
-{
- const char *last_key;
-
- frame = get_trailer_make (frame, key_path, &last_key);
- if (!frame) return NULL;
- kvp_frame_set_slot_destructively(frame, last_key, value);
- return frame;
-}
-
-KvpFrame *
-kvp_frame_set_value (KvpFrame * frame, const char * key_path,
- const KvpValue * value)
-{
- KvpValue *new_value = NULL;
- const char *last_key;
-
- frame = get_trailer_make (frame, key_path, &last_key);
- if (!frame) return NULL;
-
- if (value) new_value = kvp_value_copy(value);
- kvp_frame_set_slot_destructively(frame, last_key, new_value);
- return frame;
-}
-
-KvpValue *
-kvp_frame_replace_value_nc (KvpFrame * frame, const char * key_path,
- KvpValue * new_value)
-{
- KvpValue * old_value;
- const char *last_key;
-
- last_key = NULL;
- if (new_value)
- {
- frame = get_trailer_make (frame, key_path, &last_key);
- }
- else
- {
- frame = (KvpFrame *) get_trailer_or_null (frame, key_path, &last_key);
- }
- if (!frame) return NULL;
-
- old_value = kvp_frame_replace_slot_nc (frame, last_key, new_value);
- return old_value;
-}
-
-/* ============================================================ */
-
-KvpFrame *
-kvp_frame_add_value_nc(KvpFrame * frame, const char * path, KvpValue *value)
-{
- const char *key = NULL;
- KvpValue *oldvalue;
-
- frame = (KvpFrame *) get_trailer_or_null (frame, path, &key);
- oldvalue = kvp_frame_get_slot (frame, key);
-
- ENTER ("old frame=%s", kvp_frame_to_string(frame));
- if (oldvalue)
- {
- /* If already a glist here, just append */
- if (KVP_TYPE_GLIST == oldvalue->type)
- {
- GList * vlist = oldvalue->value.list;
- vlist = g_list_append (vlist, value);
- oldvalue->value.list = vlist;
- }
- else
- /* If some other value, convert it to a glist */
- {
- KvpValue *klist;
- GList *vlist = NULL;
-
- vlist = g_list_append (vlist, oldvalue);
- vlist = g_list_append (vlist, value);
- klist = kvp_value_new_glist_nc (vlist);
-
- kvp_frame_replace_slot_nc (frame, key, klist);
- }
- LEAVE ("new frame=%s", kvp_frame_to_string(frame));
- return frame;
- }
-
- /* Hmm, if we are here, the path doesn't exist. We need to
- * create the path, add the value to it. */
- frame = kvp_frame_set_value_nc (frame, path, value);
- LEAVE ("new frame=%s", kvp_frame_to_string(frame));
- return frame;
-}
-
-KvpFrame *
-kvp_frame_add_value(KvpFrame * frame, const char * path, KvpValue *value)
-{
- value = kvp_value_copy (value);
- frame = kvp_frame_add_value_nc (frame, path, value);
- if (!frame) kvp_value_delete (value);
- return frame;
-}
-
-void
-kvp_frame_add_gint64(KvpFrame * frame, const char * path, gint64 ival)
-{
- KvpValue *value;
- value = kvp_value_new_gint64 (ival);
- frame = kvp_frame_add_value_nc (frame, path, value);
- if (!frame) kvp_value_delete (value);
-}
-
-void
-kvp_frame_add_double(KvpFrame * frame, const char * path, double dval)
-{
- KvpValue *value;
- value = kvp_value_new_double (dval);
- frame = kvp_frame_add_value_nc (frame, path, value);
- if (!frame) kvp_value_delete (value);
-}
-
-void
-kvp_frame_add_numeric(KvpFrame * frame, const char * path, gnc_numeric nval)
-{
- KvpValue *value;
- value = kvp_value_new_gnc_numeric (nval);
- frame = kvp_frame_add_value_nc (frame, path, value);
- if (!frame) kvp_value_delete (value);
-}
-
-void
-kvp_frame_add_string(KvpFrame * frame, const char * path, const char* str)
-{
- KvpValue *value;
- value = kvp_value_new_string (str);
- frame = kvp_frame_add_value_nc (frame, path, value);
- if (!frame) kvp_value_delete (value);
-}
-
-void
-kvp_frame_add_guid(KvpFrame * frame, const char * path, const GUID *guid)
-{
- KvpValue *value;
- value = kvp_value_new_guid (guid);
- frame = kvp_frame_add_value_nc (frame, path, value);
- if (!frame) kvp_value_delete (value);
-}
-
-void
-kvp_frame_add_timespec(KvpFrame * frame, const char * path, Timespec ts)
-{
- KvpValue *value;
- value = kvp_value_new_timespec (ts);
- frame = kvp_frame_add_value_nc (frame, path, value);
- if (!frame) kvp_value_delete (value);
-}
-
-void
-kvp_frame_add_frame(KvpFrame * frame, const char * path, KvpFrame *fr)
-{
- KvpValue *value;
- value = kvp_value_new_frame (fr);
- frame = kvp_frame_add_value_nc (frame, path, value);
- if (!frame) kvp_value_delete (value);
-}
-
-void
-kvp_frame_add_frame_nc(KvpFrame * frame, const char * path, KvpFrame *fr)
-{
- KvpValue *value;
- value = kvp_value_new_frame_nc (fr);
- frame = kvp_frame_add_value_nc (frame, path, value);
- if (!frame) kvp_value_delete (value);
-}
-
-/* ============================================================ */
-
-void
-kvp_frame_set_slot(KvpFrame * frame, const char * slot,
- const KvpValue * value)
-{
- KvpValue *new_value = NULL;
-
- if (!frame) return;
-
- g_return_if_fail (slot && *slot != '\0');
-
- if(value) new_value = kvp_value_copy(value);
- kvp_frame_set_slot_destructively(frame, slot, new_value);
-}
-
-void
-kvp_frame_set_slot_nc(KvpFrame * frame, const char * slot,
- KvpValue * value)
-{
- if (!frame) return;
-
- g_return_if_fail (slot && *slot != '\0');
-
- kvp_frame_set_slot_destructively(frame, slot, value);
-}
-
-KvpValue *
-kvp_frame_get_slot(const KvpFrame * frame, const char * slot)
-{
- KvpValue *v;
- if (!frame) return NULL;
- if (!frame->hash) return NULL; /* Error ... */
- v = g_hash_table_lookup(frame->hash, slot);
- return v;
-}
-
-/* ============================================================ */
-
-void
-kvp_frame_set_slot_path (KvpFrame *frame,
- const KvpValue *new_value,
- const char *first_key, ...)
-{
- va_list ap;
- const char *key;
-
- if (!frame) return;
-
- g_return_if_fail (first_key && *first_key != '\0');
-
- va_start (ap, first_key);
-
- key = first_key;
-
- while (TRUE)
- {
- KvpValue *value;
- const char *next_key;
-
- next_key = va_arg (ap, const char *);
- if (!next_key)
- {
- kvp_frame_set_slot (frame, key, new_value);
- break;
- }
-
- g_return_if_fail (*next_key != '\0');
-
- value = kvp_frame_get_slot (frame, key);
- if (!value) {
- KvpFrame *new_frame = kvp_frame_new ();
- KvpValue *frame_value = kvp_value_new_frame (new_frame);
-
- kvp_frame_set_slot_nc (frame, key, frame_value);
-
- value = kvp_frame_get_slot (frame, key);
- if (!value) break;
- }
-
- frame = kvp_value_get_frame (value);
- if (!frame) break;
-
- key = next_key;
- }
-
- va_end (ap);
-}
-
-void
-kvp_frame_set_slot_path_gslist (KvpFrame *frame,
- const KvpValue *new_value,
- GSList *key_path)
-{
- if (!frame || !key_path) return;
-
- while (TRUE)
- {
- const char *key = key_path->data;
- KvpValue *value;
-
- if (!key)
- return;
-
- g_return_if_fail (*key != '\0');
-
- key_path = key_path->next;
- if (!key_path)
- {
- kvp_frame_set_slot (frame, key, new_value);
- return;
- }
-
- value = kvp_frame_get_slot (frame, key);
- if (!value)
- {
- KvpFrame *new_frame = kvp_frame_new ();
- KvpValue *frame_value = kvp_value_new_frame (new_frame);
-
- kvp_frame_set_slot_nc (frame, key, frame_value);
-
- value = kvp_frame_get_slot (frame, key);
- if (!value)
- return;
- }
-
- frame = kvp_value_get_frame (value);
- if (!frame)
- return;
- }
-}
-
-/* ============================================================ */
-/* decode url-encoded string, do it in place
- * + == space
- * %xx == asci char where xx is hexadecimal ascii value
- */
-
-static void
-decode (char *enc)
-{
- char * p, *w;
-
- /* Loop, convert +'s to blanks */
- p = strchr (enc, '+');
- while (p)
- {
- *p = ' ';
- p = strchr (p, '+');
- }
-
- p = strchr (enc, '%');
- w = p;
-
- while (p)
- {
- int ch,cl;
- p++;
- ch = *p - 0x30; /* ascii 0 = 0x30 */
- if (9 < ch) ch -= 0x11 - 10; /* uppercase A = 0x41 */
- if (16 < ch) ch -= 0x20; /* lowercase a = 0x61 */
-
- p++;
- cl = *p - 0x30; /* ascii 0 = 0x30 */
- if (9 < cl) cl -= 0x11 - 10; /* uppercase A = 0x41 */
- if (16 < cl) cl -= 0x20; /* lowercase a = 0x61 */
-
- *w = (char) (ch<<4 | cl);
-
- do
- {
- ++w; ++p;
- *w = *p;
- if (0x0 == *p) { p = 0; break; }
- if ('%' == *p) { break; }
- } while (*p);
- }
-}
-
-void
-kvp_frame_add_url_encoding (KvpFrame *frame, const char *enc)
-{
- char *buff, *p;
- if (!frame || !enc) return;
-
- /* Loop over all key-value pairs in the encoded string */
- buff = g_strdup (enc);
- p = buff;
- while (*p)
- {
- char *n, *v;
- n = strchr (p, '&'); /* n = next key-value */
- if (n) *n = 0x0;
-
- v = strchr (p, '='); /* v = pointer to value */
- if (!v) break;
- *v = 0x0;
- v ++;
-
- decode (p);
- decode (v);
- kvp_frame_set_slot_nc (frame, p, kvp_value_new_string(v));
-
- if (!n) break; /* no next key, we are done */
- p = ++n;
- }
-
- g_free(buff);
-}
-
-/* ============================================================ */
-
-
-gint64
-kvp_frame_get_gint64(const KvpFrame *frame, const char *path)
-{
- const char *key = NULL;
- frame = get_trailer_or_null (frame, path, &key);
- return kvp_value_get_gint64(kvp_frame_get_slot (frame, key));
-}
-
-double
-kvp_frame_get_double(const KvpFrame *frame, const char *path)
-{
- const char *key = NULL;
- frame = get_trailer_or_null (frame, path, &key);
- return kvp_value_get_double(kvp_frame_get_slot (frame, key));
-}
-
-gnc_numeric
-kvp_frame_get_numeric(const KvpFrame *frame, const char *path)
-{
- const char *key = NULL;
- frame = get_trailer_or_null (frame, path, &key);
- return kvp_value_get_numeric(kvp_frame_get_slot (frame, key));
-}
-
-char *
-kvp_frame_get_string(const KvpFrame *frame, const char *path)
-{
- const char *key = NULL;
- frame = get_trailer_or_null (frame, path, &key);
- return kvp_value_get_string(kvp_frame_get_slot (frame, key));
-}
-
-GUID *
-kvp_frame_get_guid(const KvpFrame *frame, const char *path)
-{
- const char *key = NULL;
- frame = get_trailer_or_null (frame, path, &key);
- return kvp_value_get_guid(kvp_frame_get_slot (frame, key));
-}
-
-void *
-kvp_frame_get_binary(const KvpFrame *frame, const char *path,
- guint64 * size_return)
-{
- const char *key = NULL;
- frame = get_trailer_or_null (frame, path, &key);
- return kvp_value_get_binary(kvp_frame_get_slot (frame, key), size_return);
-}
-
-Timespec
-kvp_frame_get_timespec(const KvpFrame *frame, const char *path)
-{
- const char *key = NULL;
- frame = get_trailer_or_null (frame, path, &key);
- return kvp_value_get_timespec(kvp_frame_get_slot (frame, key));
-}
-
-KvpFrame *
-kvp_frame_get_frame(const KvpFrame *frame, const char *path)
-{
- const char *key = NULL;
- frame = get_trailer_or_null (frame, path, &key);
- return kvp_value_get_frame(kvp_frame_get_slot (frame, key));
-}
-
-KvpValue *
-kvp_frame_get_value(const KvpFrame *frame, const char *path)
-{
- const char *key = NULL;
- frame = get_trailer_or_null (frame, path, &key);
- return kvp_frame_get_slot (frame, key);
-}
-
-/* ============================================================ */
-
-KvpFrame *
-kvp_frame_get_frame_gslist (KvpFrame *frame, GSList *key_path)
-{
- if (!frame) return frame;
-
- while (key_path)
- {
- const char *key = key_path->data;
-
- if (!key) return frame; /* an unusual but valid exit for this routine. */
-
- frame = get_or_make (frame, key);
- if (!frame) return frame; /* this should never happen */
-
- key_path = key_path->next;
- }
- return frame; /* this is the normal exit for this func */
-}
-
-KvpFrame *
-kvp_frame_get_frame_path (KvpFrame *frame, const char *key, ...)
-{
- va_list ap;
- if (!frame || !key) return frame;
-
- va_start (ap, key);
-
- while (key)
- {
- frame = get_or_make (frame, key);
- if (!frame) break; /* error, should never occur */
- key = va_arg (ap, const char *);
- }
-
- va_end (ap);
- return frame;
-}
-
-KvpFrame *
-kvp_frame_get_frame_slash (KvpFrame *frame, const char *key_path)
-{
- char *root;
- if (!frame || !key_path) return frame;
-
- root = g_strdup (key_path);
- frame = kvp_frame_get_frame_slash_trash (frame, root);
- g_free(root);
- return frame;
-}
-
-/* ============================================================ */
-
-KvpValue *
-kvp_frame_get_slot_path (KvpFrame *frame,
- const char *first_key, ...)
-{
- va_list ap;
- KvpValue *value;
- const char *key;
-
- if (!frame || !first_key) return NULL;
-
- va_start (ap, first_key);
-
- key = first_key;
- value = NULL;
-
- while (TRUE)
- {
- value = kvp_frame_get_slot (frame, key);
- if (!value) break;
-
- key = va_arg (ap, const char *);
- if (!key) break;
-
- frame = kvp_value_get_frame (value);
- if (!frame)
- {
- value = NULL;
- break;
- }
- }
-
- va_end (ap);
-
- return value;
-}
-
-KvpValue *
-kvp_frame_get_slot_path_gslist (KvpFrame *frame,
- GSList *key_path)
-{
- if (!frame || !key_path) return NULL;
-
- while (TRUE)
- {
- const char *key = key_path->data;
- KvpValue *value;
-
- if (!key) return NULL;
-
- value = kvp_frame_get_slot (frame, key);
- if (!value) return NULL;
-
- key_path = key_path->next;
- if (!key_path) return value;
-
- frame = kvp_value_get_frame (value);
- if (!frame) return NULL;
- }
-}
-
-/********************************************************************
- * kvp glist functions
- ********************************************************************/
-
-void
-kvp_glist_delete(GList * list)
-{
- GList *node;
- if(!list) return;
-
- /* Delete the data in the list */
- for (node=list; node; node=node->next)
- {
- KvpValue *val = node->data;
- kvp_value_delete(val);
- }
-
- /* Free the backbone */
- g_list_free(list);
-}
-
-GList *
-kvp_glist_copy(const GList * list)
-{
- GList * retval = NULL;
- GList * lptr;
-
- if (!list) return retval;
-
- /* Duplicate the backbone of the list (this duplicates the POINTERS
- * to the values; we need to deep-copy the values separately) */
- retval = g_list_copy((GList *) list);
-
- /* This step deep-copies the values */
- for(lptr = retval; lptr; lptr = lptr->next)
- {
- lptr->data = kvp_value_copy(lptr->data);
- }
-
- return retval;
-}
-
-gint
-kvp_glist_compare(const GList * list1, const GList * list2)
-{
- const GList *lp1;
- const GList *lp2;
-
- if(list1 == list2) return 0;
-
- /* Nothing is always less than something */
- if(!list1 && list2) return -1;
- if(list1 && !list2) return 1;
-
- lp1 = list1;
- lp2 = list2;
- while(lp1 && lp2)
- {
- KvpValue *v1 = (KvpValue *) lp1->data;
- KvpValue *v2 = (KvpValue *) lp2->data;
- gint vcmp = kvp_value_compare(v1, v2);
- if(vcmp != 0) return vcmp;
- lp1 = lp1->next;
- lp2 = lp2->next;
- }
- if(!lp1 && lp2) return -1;
- if(!lp2 && lp1) return 1;
- return 0;
-}
-
-/********************************************************************
- * KvpValue functions
- ********************************************************************/
-
-KvpValue *
-kvp_value_new_gint64(gint64 value)
-{
- KvpValue * retval = g_new0(KvpValue, 1);
- retval->type = KVP_TYPE_GINT64;
- retval->value.int64 = value;
- return retval;
-}
-
-KvpValue *
-kvp_value_new_double(double value)
-{
- KvpValue * retval = g_new0(KvpValue, 1);
- retval->type = KVP_TYPE_DOUBLE;
- retval->value.dbl = value;
- return retval;
-}
-
-KvpValue *
-kvp_value_new_numeric(gnc_numeric value)
-{
- KvpValue * retval = g_new0(KvpValue, 1);
- retval->type = KVP_TYPE_NUMERIC;
- retval->value.numeric = value;
- return retval;
-}
-
-KvpValue *
-kvp_value_new_string(const char * value)
-{
- KvpValue * retval;
- if (!value) return NULL;
-
- retval = g_new0(KvpValue, 1);
- retval->type = KVP_TYPE_STRING;
- retval->value.str = g_strdup(value);
- return retval;
-}
-
-KvpValue *
-kvp_value_new_guid(const GUID * value)
-{
- KvpValue * retval;
- if (!value) return NULL;
-
- retval = g_new0(KvpValue, 1);
- retval->type = KVP_TYPE_GUID;
- retval->value.guid = g_new0(GUID, 1);
- memcpy(retval->value.guid, value, sizeof(GUID));
- return retval;
-}
-
-KvpValue *
-kvp_value_new_timespec(Timespec value)
-{
- KvpValue * retval = g_new0(KvpValue, 1);
- retval->type = KVP_TYPE_TIMESPEC;
- retval->value.timespec = value;
- return retval;
-}
-
-KvpValue *
-kvp_value_new_binary(const void * value, guint64 datasize)
-{
- KvpValue * retval;
- if (!value) return NULL;
-
- retval = g_new0(KvpValue, 1);
- retval->type = KVP_TYPE_BINARY;
- retval->value.binary.data = g_new0(char, datasize);
- retval->value.binary.datasize = datasize;
- memcpy(retval->value.binary.data, value, datasize);
- return retval;
-}
-
-KvpValue *
-kvp_value_new_binary_nc(void * value, guint64 datasize)
-{
- KvpValue * retval;
- if (!value) return NULL;
-
- retval = g_new0(KvpValue, 1);
- retval->type = KVP_TYPE_BINARY;
- retval->value.binary.data = value;
- retval->value.binary.datasize = datasize;
- return retval;
-}
-
-KvpValue *
-kvp_value_new_glist(const GList * value)
-{
- KvpValue * retval;
- if (!value) return NULL;
-
- retval = g_new0(KvpValue, 1);
- retval->type = KVP_TYPE_GLIST;
- retval->value.list = kvp_glist_copy(value);
- return retval;
-}
-
-KvpValue *
-kvp_value_new_glist_nc(GList * value)
-{
- KvpValue * retval;
- if (!value) return NULL;
-
- retval = g_new0(KvpValue, 1);
- retval->type = KVP_TYPE_GLIST;
- retval->value.list = value;
- return retval;
-}
-
-KvpValue *
-kvp_value_new_frame(const KvpFrame * value)
-{
- KvpValue * retval;
- if (!value) return NULL;
-
- retval = g_new0(KvpValue, 1);
- retval->type = KVP_TYPE_FRAME;
- retval->value.frame = kvp_frame_copy(value);
- return retval;
-}
-
-KvpValue *
-kvp_value_new_frame_nc(KvpFrame * value)
-{
- KvpValue * retval;
- if (!value) return NULL;
-
- retval = g_new0(KvpValue, 1);
- retval->type = KVP_TYPE_FRAME;
- retval->value.frame = value;
- return retval;
-}
-
-void
-kvp_value_delete(KvpValue * value)
-{
- if(!value) return;
-
- switch(value->type)
- {
- case KVP_TYPE_STRING:
- g_free(value->value.str);
- break;
- case KVP_TYPE_GUID:
- g_free(value->value.guid);
- break;
- case KVP_TYPE_BINARY:
- g_free(value->value.binary.data);
- break;
- case KVP_TYPE_GLIST:
- kvp_glist_delete(value->value.list);
- break;
- case KVP_TYPE_FRAME:
- kvp_frame_delete(value->value.frame);
- break;
-
- case KVP_TYPE_GINT64:
- case KVP_TYPE_DOUBLE:
- case KVP_TYPE_NUMERIC:
- default:
- break;
- }
- g_free(value);
-}
-
-KvpValueType
-kvp_value_get_type(const KvpValue * value)
-{
- if (!value) return -1;
- return value->type;
-}
-
-gint64
-kvp_value_get_gint64(const KvpValue * value)
-{
- if (!value) return 0;
- if(value->type == KVP_TYPE_GINT64) {
- return value->value.int64;
- }
- else {
- return 0;
- }
-}
-
-double
-kvp_value_get_double(const KvpValue * value)
-{
- if (!value) return 0.0;
- if(value->type == KVP_TYPE_DOUBLE) {
- return value->value.dbl;
- }
- else {
- return 0.0;
- }
-}
-
-gnc_numeric
-kvp_value_get_numeric(const KvpValue * value)
-{
- if (!value) return gnc_numeric_zero ();
- if(value->type == KVP_TYPE_NUMERIC) {
- return value->value.numeric;
- }
- else {
- return gnc_numeric_zero ();
- }
-}
-
-char *
-kvp_value_get_string(const KvpValue * value)
-{
- if (!value) return NULL;
- if(value->type == KVP_TYPE_STRING) {
- return value->value.str;
- }
- else {
- return NULL;
- }
-}
-
-GUID *
-kvp_value_get_guid(const KvpValue * value)
-{
- if (!value) return NULL;
- if(value->type == KVP_TYPE_GUID) {
- return value->value.guid;
- }
- else {
- return NULL;
- }
-}
-
-Timespec
-kvp_value_get_timespec(const KvpValue * value)
-{
- Timespec ts; ts.tv_sec = 0; ts.tv_nsec = 0;
- if (!value) return ts;
- if (value->type == KVP_TYPE_TIMESPEC)
- return value->value.timespec;
- else
- return ts;
-}
-
-void *
-kvp_value_get_binary(const KvpValue * value, guint64 * size_return)
-{
- if (!value)
- {
- if (size_return)
- *size_return = 0;
- return NULL;
- }
-
- if(value->type == KVP_TYPE_BINARY) {
- if (size_return)
- *size_return = value->value.binary.datasize;
- return value->value.binary.data;
- }
- else {
- if (size_return)
- *size_return = 0;
- return NULL;
- }
-}
-
-GList *
-kvp_value_get_glist(const KvpValue * value)
-{
- if (!value) return NULL;
- if(value->type == KVP_TYPE_GLIST) {
- return value->value.list;
- }
- else {
- return NULL;
- }
-}
-
-KvpFrame *
-kvp_value_get_frame(const KvpValue * value)
-{
- if (!value) return NULL;
- if(value->type == KVP_TYPE_FRAME) {
- return value->value.frame;
- }
- else {
- return NULL;
- }
-}
-
-KvpFrame *
-kvp_value_replace_frame_nc(KvpValue *value, KvpFrame * newframe)
-{
- KvpFrame *oldframe;
- if (!value) return NULL;
- if (KVP_TYPE_FRAME != value->type) return NULL;
-
- oldframe = value->value.frame;
- value->value.frame = newframe;
- return oldframe;
-}
-
-GList *
-kvp_value_replace_glist_nc(KvpValue * value, GList *newlist)
-{
- GList *oldlist;
- if (!value) return NULL;
- if (KVP_TYPE_GLIST != value->type) return NULL;
-
- oldlist = value->value.list;
- value->value.list = newlist;
- return oldlist;
-}
-
-/* manipulators */
-
-KvpValue *
-kvp_value_copy(const KvpValue * value)
-{
- if(!value) return NULL;
-
- switch(value->type) {
- case KVP_TYPE_GINT64:
- return kvp_value_new_gint64(value->value.int64);
- break;
- case KVP_TYPE_DOUBLE:
- return kvp_value_new_double(value->value.dbl);
- break;
- case KVP_TYPE_NUMERIC:
- return kvp_value_new_gnc_numeric(value->value.numeric);
- break;
- case KVP_TYPE_STRING:
- return kvp_value_new_string(value->value.str);
- break;
- case KVP_TYPE_GUID:
- return kvp_value_new_guid(value->value.guid);
- break;
- case KVP_TYPE_TIMESPEC:
- return kvp_value_new_timespec(value->value.timespec);
- break;
- case KVP_TYPE_BINARY:
- return kvp_value_new_binary(value->value.binary.data,
- value->value.binary.datasize);
- break;
- case KVP_TYPE_GLIST:
- return kvp_value_new_glist(value->value.list);
- break;
- case KVP_TYPE_FRAME:
- return kvp_value_new_frame(value->value.frame);
- break;
- }
- return NULL;
-}
-
-void
-kvp_frame_for_each_slot(KvpFrame *f,
- void (*proc)(const char *key,
- KvpValue *value,
- gpointer data),
- gpointer data)
-{
- if(!f) return;
- if(!proc) return;
- if(!(f->hash)) return;
-
- g_hash_table_foreach(f->hash, (GHFunc) proc, data);
-}
-
-gint
-double_compare(double d1, double d2)
-{
- if(isnan(d1) && isnan(d2)) return 0;
- if(d1 < d2) return -1;
- if(d1 > d2) return 1;
- return 0;
-}
-
-gint
-kvp_value_compare(const KvpValue * kva, const KvpValue * kvb)
-{
- if(kva == kvb) return 0;
- /* nothing is always less than something */
- if(!kva && kvb) return -1;
- if(kva && !kvb) return 1;
-
- if(kva->type < kvb->type) return -1;
- if(kva->type > kvb->type) return 1;
-
- switch(kva->type) {
- case KVP_TYPE_GINT64:
- 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;
- case KVP_TYPE_STRING:
- return strcmp(kva->value.str, kvb->value.str);
- break;
- case KVP_TYPE_GUID:
- return guid_compare(kva->value.guid, kvb->value.guid);
- break;
- case KVP_TYPE_TIMESPEC:
- return timespec_cmp(&(kva->value.timespec), &(kvb->value.timespec));
- 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;
- return memcmp(kva->value.binary.data,
- kvb->value.binary.data,
- kva->value.binary.datasize);
- break;
- case KVP_TYPE_GLIST:
- return kvp_glist_compare(kva->value.list, kvb->value.list);
- break;
- case KVP_TYPE_FRAME:
- return kvp_frame_compare(kva->value.frame, kvb->value.frame);
- break;
- }
- PERR ("reached unreachable code.");
- return FALSE;
-}
-
-typedef struct {
- gint compare;
- KvpFrame *other_frame;
-} kvp_frame_cmp_status;
-
-static void
-kvp_frame_compare_helper(const char *key, KvpValue * val, gpointer data)
-{
- kvp_frame_cmp_status *status = (kvp_frame_cmp_status *) data;
- if(status->compare == 0) {
- KvpFrame *other_frame = status->other_frame;
- KvpValue *other_val = kvp_frame_get_slot(other_frame, key);
-
- if(other_val) {
- status->compare = kvp_value_compare(val, other_val);
- } else {
- status->compare = 1;
- }
- }
-}
-
-gint
-kvp_frame_compare(const KvpFrame *fa, const KvpFrame *fb)
-{
- kvp_frame_cmp_status status;
-
- if(fa == fb) return 0;
- /* nothing is always less than something */
- if(!fa && fb) return -1;
- if(fa && !fb) return 1;
-
- /* nothing is always less than something */
- if(!fa->hash && fb->hash) return -1;
- if(fa->hash && !fb->hash) return 1;
-
- status.compare = 0;
- status.other_frame = (KvpFrame *) fb;
-
- kvp_frame_for_each_slot((KvpFrame *) fa, kvp_frame_compare_helper, &status);
-
- if (status.compare != 0)
- return status.compare;
-
- status.other_frame = (KvpFrame *) fa;
-
- kvp_frame_for_each_slot((KvpFrame *) fb, kvp_frame_compare_helper, &status);
-
- 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_append_printf(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((KvpValue *)cursor->data);
- tmp2 = g_strdup_printf("%s %s,", tmp1, tmp3 ? tmp3 : "");
- g_free(tmp1);
- g_free(tmp3);
- tmp1 = tmp2;
- }
-
- tmp2 = g_strdup_printf("%s ]", tmp1);
- g_free(tmp1);
-
- return tmp2;
-}
-
-gchar*
-kvp_value_to_bare_string(const KvpValue *val)
-{
- gchar *tmp1;
- gchar *tmp2;
- const gchar *ctmp;
-
- g_return_val_if_fail(val, NULL);
-
- switch(kvp_value_get_type(val))
- {
- case KVP_TYPE_GINT64:
- return g_strdup_printf("%" G_GINT64_FORMAT, kvp_value_get_gint64(val));
- break;
-
- case KVP_TYPE_DOUBLE:
- return g_strdup_printf("(%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("%s", tmp1 ? tmp1 : "");
- g_free(tmp1);
- return tmp2;
- break;
-
- case KVP_TYPE_STRING:
- tmp1 = kvp_value_get_string (val);
- return g_strdup_printf("%s", tmp1 ? tmp1 : "");
- break;
-
- case KVP_TYPE_GUID:
- ctmp = guid_to_string(kvp_value_get_guid(val));
- tmp2 = g_strdup_printf("%s", ctmp ? ctmp : "");
- return tmp2;
- break;
-
- case KVP_TYPE_TIMESPEC:
- tmp1 = g_new0 (char, 40);
- gnc_timespec_to_iso8601_buff (kvp_value_get_timespec (val), tmp1);
- tmp2 = g_strdup_printf("%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("%s", tmp1 ? tmp1 : "");
- }
- break;
-
- case KVP_TYPE_GLIST:
- tmp1 = kvp_value_glist_to_string(kvp_value_get_glist(val));
- tmp2 = g_strdup_printf("%s", tmp1 ? 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("%s", tmp1 ? tmp1 : "");
- g_free(tmp1);
- return tmp2;
- break;
-
- default:
- return g_strdup_printf(" ");
- break;
- }
-}
-
-gchar*
-kvp_value_to_string(const KvpValue *val)
-{
- gchar *tmp1;
- gchar *tmp2;
- const gchar *ctmp;
-
- g_return_val_if_fail(val, NULL);
-
- switch(kvp_value_get_type(val))
- {
- case KVP_TYPE_GINT64:
- return g_strdup_printf("KVP_VALUE_GINT64(%" G_GINT64_FORMAT ")",
- 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 ? tmp1 : "");
- g_free(tmp1);
- return tmp2;
- break;
-
- case KVP_TYPE_STRING:
- tmp1 = kvp_value_get_string (val);
- return g_strdup_printf("KVP_VALUE_STRING(%s)", tmp1 ? tmp1 : "");
- break;
-
- case KVP_TYPE_GUID:
- /* THREAD-UNSAFE */
- ctmp = guid_to_string(kvp_value_get_guid(val));
- tmp2 = g_strdup_printf("KVP_VALUE_GUID(%s)", ctmp ? ctmp : "");
- return tmp2;
- break;
-
- case KVP_TYPE_TIMESPEC:
- tmp1 = g_new0 (char, 40);
- gnc_timespec_to_iso8601_buff (kvp_value_get_timespec (val), tmp1);
- tmp2 = g_strdup_printf("KVP_VALUE_TIMESPEC(%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 ? 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 ? 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 ? 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((KvpValue *)value);
-
- *str = g_strdup_printf("%s %s => %s,\n",
- *str ? *str : "",
- key ? (char *) key : "",
- tmp_val ? tmp_val : "");
-
- g_free(old_data);
- g_free(tmp_val);
-}
-
-gchar*
-kvp_frame_to_string(const KvpFrame *frame)
-{
- gchar *tmp1;
-
- g_return_val_if_fail (frame != NULL, NULL);
-
- tmp1 = g_strdup_printf("{\n");
-
- if (frame->hash)
- 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 KvpFrame *frame)
-{
- g_return_val_if_fail (frame != NULL, NULL);
- return frame->hash;
-}
-
-/* ========================== END OF FILE ======================= */
Deleted: gnucash/trunk/src/engine/kvp_frame.h
===================================================================
--- gnucash/trunk/src/engine/kvp_frame.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/kvp_frame.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,694 +0,0 @@
-/********************************************************************\
- * kvp_frame.h -- Implements a key-value frame system *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-/** @addtogroup KVP
-
- * A KvpFrame is a set of associations between character strings
- * (keys) and KvpValue structures. A KvpValue is a union with
- * possible types enumerated in the KvpValueType enum, and includes,
- * among other things, ints, doubles, strings, guid's, lists, time
- * and numeric values. KvpValues may also be other frames, so
- * KVP is inherently hierarchical.
- *
- * Values are stored in a 'slot' associated with a key.
- * 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.
- *
- * A 'path' is a sequence of keys that can be followed to a value.
- * Paths may be specified as varargs (variable number of arguments
- * to a subrutine, NULL-terminated), as a GSList, or as a standard
- * URL-like path name. The later is parsed and treated in the same
- * way as file paths would be: / separates keys, /./ is treated as /
- * and /../ means backup one level. Repeated slashes are treated
- * as one slash.
- *
- * Note that although, in principle, keys may contain the / and . and
- * .. characters, doing so may lead to confusion, and will make
- * path-string parsing routines fail. In other words, don't use
- * a key such as 'some/key' or 'some/./other/../key' because you
- * may get unexpected results.
- *
- * To set a value into a frame, you will want to use one of the
- * kvp_frame_set_xxx() routines. Most of the other routines provide
- * only low-level access that you probably shouldn't use.
-
-@{
-*/
-/** @file kvp_frame.h
- @brief A key-value frame system
- @author Copyright (C) 2000 Bill Gribble
- @author Copyright (C) 2003 Linas Vepstas <linas at linas.org>
-*/
-
-#ifndef KVP_FRAME_H
-#define KVP_FRAME_H
-
-#include <glib.h>
-
-#include "gnc-date.h"
-#include "gnc-numeric.h"
-#include "guid.h"
-
-#define QOF_MOD_KVP "qof-kvp"
-
-/** Opaque frame structure */
-typedef struct _KvpFrame KvpFrame;
-
-/** A KvpValue is a union with possible types enumerated in the
- * KvpValueType enum. */
-typedef struct _KvpValue KvpValue;
-
-/** \brief possible types in the union KvpValue
- * \todo : People have asked for boolean values,
- * e.g. in xaccAccountSetAutoInterestXfer
- *
- * \todo In the long run, this should be synchronized with the
- * core QOF types, which in turn should be synced to the g_types
- * in GLib. Unfortunately, this requires writing a pile of code
- * to handle all of the different cases.
- * An alternative might be to make kvp values inherit from the
- * core g_types (i.e. add new core g_types) ??
- */
-typedef enum {
- KVP_TYPE_GINT64=1, /**< QOF_TYPE_INT64 gint64 */
- KVP_TYPE_DOUBLE, /**< QOF_TYPE_DOUBLE gdouble */
- KVP_TYPE_NUMERIC, /**< QOF_TYPE_NUMERIC */
- KVP_TYPE_STRING, /**< QOF_TYPE_STRING gchar* */
- KVP_TYPE_GUID, /**< QOF_TYPE_GUID */
- KVP_TYPE_TIMESPEC, /**< QOF_TYPE_DATE */
- KVP_TYPE_BINARY, /**< no QOF equivalent. */
- KVP_TYPE_GLIST, /**< no QOF equivalent. */
- KVP_TYPE_FRAME /**< no QOF equivalent. */
-} KvpValueType;
-
-/** \deprecated Deprecated backwards compat tokens
-
-do \b not use these in new code.
-*/
-#define kvp_frame KvpFrame
-#define kvp_value KvpValue
-#define kvp_value_t KvpValueType
-
-/** @name KvpFrame Constructors
- @{
-*/
-
-/** Return a new empty instance of KvpFrame */
-KvpFrame * kvp_frame_new(void);
-
-/** Perform a deep (recursive) delete of the frame and any subframes.
-
- * kvp_frame_delete and kvp_value_delete are deep (recursive) deletes.
- * kvp_frame_copy and kvp_value_copy are deep value copies.
- */
-void kvp_frame_delete(KvpFrame * frame);
-
-/** Perform a deep (recursive) value copy, copying the fraame,
- * subframes, and the values as well. */
-KvpFrame * kvp_frame_copy(const KvpFrame * frame);
-
-/** Return TRUE if the KvpFrame is empty */
-gboolean kvp_frame_is_empty(KvpFrame * frame);
-
-/** @} */
-
-/** @name KvpFrame Basic Value Storing
-@{
-*/
-
-/** store the value of the
- * gint64 at the indicated path. If not all frame components of
- * the path exist, they are created.
- *
- */
-void kvp_frame_set_gint64(KvpFrame * frame, const char * path, gint64 ival);
-/**
- * store the value of the
- * double at the indicated path. If not all frame components of
- * the path exist, they are created.
-*/
-void kvp_frame_set_double(KvpFrame * frame, const char * path, double dval);
-
-/** \deprecated
-
-Use kvp_frame_set_numeric instead of kvp_frame_set_gnc_numeric
-*/
-#define kvp_frame_set_gnc_numeric kvp_frame_set_numeric
-/** store the value of the
- * gnc_numeric at the indicated path.
- * If not all frame components of
- * the path exist, they are created.
- */
-void kvp_frame_set_numeric(KvpFrame * frame, const char * path, gnc_numeric nval);
-/** store the value of the
- * Timespec at the indicated path.
- * If not all frame components of
- * the path exist, they are created.
- */
-void kvp_frame_set_timespec(KvpFrame * frame, const char * path, Timespec ts);
-
-/** \deprecated
-
-Use kvp_frame_set_string instead of kvp_frame_set_str
-*/
-#define kvp_frame_set_str kvp_frame_set_string
-
-/** \brief Store a copy of the string at the indicated path.
-
- * If not all frame components of the path
- * exist, they are created. If there was another string previously
- * stored at that path, the old copy is deleted.
- *
- * Similarly, the set_guid and set_frame will make copies and
- * store those. Old copies, if any, are deleted.
- *
- * The kvp_frame_set_frame_nc() routine works as above, but does
- * *NOT* copy the frame.
- */
-void kvp_frame_set_string(KvpFrame * frame, const char * path, const char* str);
-void kvp_frame_set_guid(KvpFrame * frame, const char * path, const GUID *guid);
-
-void kvp_frame_set_frame(KvpFrame *frame, const char *path, KvpFrame *chld);
-void kvp_frame_set_frame_nc(KvpFrame *frame, const char *path, KvpFrame *chld);
-
-/** The kvp_frame_set_value() routine copies the value into the frame,
- * at the location 'path'. If the path contains slashes '/', these
- * are assumed to represent a sequence of keys. The returned value
- * is a pointer to the actual frame into which the value was inserted;
- * it is NULL if the frame couldn't be found (and thus the value wasn't
- * inserted). The old value at this location, if any, is destroyed.
- *
- * Pointers passed as arguments into this routine are the responsibility
- * of the caller; the pointers are *not* taken over or managed.
- */
-KvpFrame * kvp_frame_set_value(KvpFrame * frame,
- const char * path, const KvpValue * value);
-/**
- * The kvp_frame_set_value_nc() routine puts the value (without copying
- * it) into the frame, putting it at the location 'path'. If the path
- * contains slashes '/', these are assumed to represent a sequence of keys.
- * The returned value is a pointer to the actual frame into which the value
- * was inserted; it is NULL if the frame couldn't be found (and thus the
- * value wasn't inserted). The old value at this location, if any,
- * is destroyed.
- *
- * This routine is handy for avoiding excess memory allocations & frees.
- * Note that because the KvpValue was grabbed, you can't just delete
- * unless you remove the key as well (or unless you replace the value).
- */
-KvpFrame * kvp_frame_set_value_nc(KvpFrame * frame,
- const char * path, KvpValue * value);
-
-/** The kvp_frame_replace_value_nc() routine places the new value
- * at the indicated path. It returns the old value, if any.
- * It returns NULL if there was an error, or if there was no
- * old value. If the path doesn't exist, it is created, unless
- * new_value is NULL. Passing in a NULL new_value has the
- * effect of deleting the trailing slot (i.e. the trailing path
- * element).
- */
-KvpValue * kvp_frame_replace_value_nc (KvpFrame * frame, const char * slot,
- KvpValue * new_value);
-/** @} */
-/** @name KvpFrame URL handling
- @{
-*/
-/** The kvp_frame_add_url_encoding() routine will parse the
- * value string, assuming it to be URL-encoded in the standard way,
- * turning it into a set of key-value pairs, and adding those to the
- * indicated frame. URL-encoded strings are the things that are
- * returned by web browsers when a form is filled out. For example,
- * 'start-date=June&end-date=November' consists of two keys,
- * 'start-date' and 'end-date', which have the values 'June' and
- * 'November', respectively. This routine also handles % encoding.
- *
- * This routine treats all values as strings; it does *not* attempt
- * to perform any type-conversion.
- * */
-void kvp_frame_add_url_encoding (KvpFrame *frame, const char *enc);
-/** @} */
-
-/** @name KvpFrame Glist Bag Storing
- @{
-*/
-
-/** The kvp_frame_add_gint64() routine will add the value of the
- * gint64 to the glist bag of values at the indicated path.
- * If not all frame components of the path exist, they are
- * created. If the value previously stored at this path was
- * not a glist bag, then a bag will be formed there, the old
- * value placed in the bag, and the new value added to the bag.
- *
- * Similarly, the add_double, add_numeric, and add_timespec
- * routines perform the same function, for each of the respective
- * types.
- */
-void kvp_frame_add_gint64(KvpFrame * frame, const char * path, gint64 ival);
-void kvp_frame_add_double(KvpFrame * frame, const char * path, double dval);
-/** \deprecated
-
-Use kvp_frame_add_numeric instead of kvp_frame_add_gnc_numeric
-*/
-#define kvp_frame_add_gnc_numeric kvp_frame_add_numeric
-
-void kvp_frame_add_numeric(KvpFrame * frame, const char * path, gnc_numeric nval);
-void kvp_frame_add_timespec(KvpFrame * frame, const char * path, Timespec ts);
-
-/** \deprecated
-
-Use kvp_frame_add_string instead of kvp_frame_add_str
-*/
-#define kvp_frame_add_str kvp_frame_add_string
-
-/** \brief Copy of the string to the glist bag at the indicated path.
-
- * If not all frame components
- * of the path exist, they are created. If there was another
- * item previously stored at that path, then the path is converted
- * to a bag, and the old value, along with the new value, is added
- * to the bag.
- *
- * Similarly, the add_guid and add_frame will make copies and
- * add those.
- *
- * The kvp_frame_add_frame_nc() routine works as above, but does
- * *NOT* copy the frame.
- */
-void kvp_frame_add_string(KvpFrame * frame, const char * path, const char* str);
-void kvp_frame_add_guid(KvpFrame * frame, const char * path, const GUID *guid);
-
-void kvp_frame_add_frame(KvpFrame *frame, const char *path, KvpFrame *chld);
-void kvp_frame_add_frame_nc(KvpFrame *frame, const char *path, KvpFrame *chld);
-
-/* The kvp_frame_add_value() routine will add a copy of the value
- * to the glist bag at the indicated path. If not all frame components
- * of the path exist, they are created. If there was another
- * item previously stored at that path, then the path is converted
- * to a bag, and the old value, along with the new value, is added
- * to the bag. This routine returns the pointer to the last frame
- * (the actual frame to which the value was added), or NULL if there
- * was an error of any sort (typically, a parse error in the path).
- *
- * The *_nc() routine is analogous, except that it doesn't copy the
- * value.
- */
-KvpFrame * kvp_frame_add_value(KvpFrame * frame, const char * path, KvpValue *value);
-KvpFrame * kvp_frame_add_value_nc(KvpFrame * frame, const char * path, KvpValue *value);
-
-
-/** @} */
-
-/** @name KvpFrame Value Fetching
-
- Value accessors. These all take a unix-style slash-separated
- path as an argument, and return the value stored at that location.
- If the object at the end of that path is not of the type that was
- asked for, then a NULL or a zero is returned. So, for example,
- asking for a string when the path stored an int will return a NULL.
- In some future date, this may be changed to a looser type system,
- such as perl's automatic re-typing (e.g. an integer value might be
- converted to a printed string representing that value).
-
- If any part of the path does not exist, then NULL or zero will be
- returned.
-
- The values returned for GUID, binary, GList, KvpFrame and string
- are "non-copying" -- the returned item is the actual item stored.
- Do not delete this item unless you take the required care to avoid
- possible bad pointer derefrences (i.e. core dumps). Also, be
- careful hanging on to those references if you are also storing
- at the same path names: the referenced item will be freed during
- the store.
-
- That is, if you get a string value (or guid, binary or frame),
- and then store something else at that path, the string that you've
- gotten will be freed during the store (internally, by the set_*()
- routines), and you will be left hanging onto an invalid pointer.
-@{
-*/
-
-gint64 kvp_frame_get_gint64(const KvpFrame *frame, const char *path);
-double kvp_frame_get_double(const KvpFrame *frame, const char *path);
-gnc_numeric kvp_frame_get_numeric(const KvpFrame *frame, const char *path);
-char * kvp_frame_get_string(const KvpFrame *frame, const char *path);
-GUID * kvp_frame_get_guid(const KvpFrame *frame, const char *path);
-void * kvp_frame_get_binary(const KvpFrame *frame, const char *path,
- guint64 * size_return);
-Timespec kvp_frame_get_timespec(const KvpFrame *frame, const char *path);
-KvpValue * kvp_frame_get_value(const KvpFrame *frame, const char *path);
-
-/** Value accessor. Takes a unix-style slash-separated path as an
- * argument, and return the KvpFrame stored at that location. If the
- * KvpFrame does not exist, then a NULL is returned.
- *
- * @note The semantics here have changed: In gnucash-1.8, if the
- * KvpFrame did not exist, this function automatically created one
- * and returned it. However, now this function will return NULL in
- * this case and the caller has to create a KvpFrame on his own. The
- * old functionality is now implemented by
- * kvp_frame_get_frame_path(). This happened on 2003-09-14, revision
- * 1.31. FIXME: Is it really a good idea to change the semantics of
- * an existing function and move the old semantics to a new
- * function??! It would save us a lot of trouble if the new semantics
- * would have been available in a new function!
- *
- * @return The KvpFrame at the specified path, or NULL if it doesn't
- * exist.
-*/
-KvpFrame * kvp_frame_get_frame(const KvpFrame *frame, const char *path);
-
-/** This routine returns the last frame of the path.
- * If the frame path doesn't exist, it is created.
- * Note that this is *VERY DIFFERENT FROM* like kvp_frame_get_frame()
- *
- * @note The semantics of this function implemented the gnucash-1.8
- * behaviour of kvp_frame_get_frame: In gnucash-1.8, if the KvpFrame
- * did not exist, kvp_frame_get_frame automatically created one and
- * returned it. However, now that one will return NULL in this case
- * and the caller has to create a KvpFrame on his own. The old
- * functionality is implemented by this
- * kvp_frame_get_frame_path(). This happened on 2003-09-14, revision
- * 1.31.
- */
-KvpFrame * kvp_frame_get_frame_path (KvpFrame *frame, const char *,...);
-
-/** This routine returns the last frame of the path.
- * If the frame path doesn't exist, it is created.
- * Note that this is *VERY DIFFERENT FROM* kvp_frame_get_frame()
- */
-KvpFrame * kvp_frame_get_frame_gslist (KvpFrame *frame,
- GSList *key_path);
-
-/** This routine returns the last frame of the path.
- * If the frame path doesn't exist, it is created.
- * Note that this is *VERY DIFFERENT FROM* kvp_frame_get_frame()
- *
- * The kvp_frame_get_frame_slash() routine takes a single string
- * where the keys are separated by slashes; thus, for example:
- * /this/is/a/valid/path and///so//is////this/
- * Multiple slashes are compresed. Leading slash is optional.
- * The pointers . and .. are *not* currently followed/obeyed.
- * (This is a bug that needs fixing).
- */
-KvpFrame * kvp_frame_get_frame_slash (KvpFrame *frame,
- const char *path);
-
-/** @} */
-/** @name KvpFrame KvpValue low-level storing routines.
-
-You probably shouldn't be using these low-level routines
-
- All of the kvp_frame_set_slot_*() routines set the slot values
- "destructively", in that if there was an old value there, that
- old value is destroyed (and the memory freed). Thus, one
- should not hang on to value pointers, as these will get
- trashed if set_slot is called on the corresponding key.
-
- If you want the old value, use kvp_frame_replace_slot().
- @{
-*/
-
-/** The kvp_frame_replace_slot_nc() routine places the new value into
- * the indicated frame, for the given key. It returns the old
- * value, if any. It returns NULL if the slot doesn't exist,
- * if there was some other an error, or if there was no old value.
- * Passing in a NULL new_value has the effect of deleting that
- * slot.
- */
-KvpValue * kvp_frame_replace_slot_nc (KvpFrame * frame, const char * slot,
- KvpValue * new_value);
-
-
-/** The kvp_frame_set_slot() routine copies the value into the frame,
- * associating it with a copy of 'key'. Pointers passed as arguments
- * into kvp_frame_set_slot are the responsibility of the caller;
- * the pointers are *not* taken over or managed. The old value at
- * this location, if any, is destroyed.
- */
-void kvp_frame_set_slot(KvpFrame * frame,
- const char * key, const KvpValue * value);
-/**
- * The kvp_frame_set_slot_nc() routine puts the value (without copying
- * it) into the frame, associating it with a copy of 'key'. This
- * routine is handy for avoiding excess memory allocations & frees.
- * Note that because the KvpValue was grabbed, you can't just delete
- * unless you remove the key as well (or unless you replace the value).
- * The old value at this location, if any, is destroyed.
- */
-void kvp_frame_set_slot_nc(KvpFrame * frame,
- const char * key, KvpValue * value);
-
-/** The kvp_frame_set_slot_path() routine walks the hierarchy,
- * using the key values to pick each branch. When the terminal
- * node is reached, the value is copied into it. The old value
- * at this location, if any, is destroyed.
- */
-void kvp_frame_set_slot_path (KvpFrame *frame,
- const KvpValue *value,
- const char *first_key, ...);
-
-/** The kvp_frame_set_slot_path_gslist() routine walks the hierarchy,
- * using the key values to pick each branch. When the terminal node
- * is reached, the value is copied into it. The old value at this
- * location, if any, is destroyed.
- */
-void kvp_frame_set_slot_path_gslist (KvpFrame *frame,
- const KvpValue *value,
- GSList *key_path);
-
-/** @} */
-
-/** @name KvpFrame KvpValue Low-Level Retrieval Routines
-
- You probably shouldn't be using these low-level routines
-
- Returns the KvpValue in the given KvpFrame 'frame' that is
- associated with 'key'. If there is no key in the frame, NULL
- is returned. If the value associated with the key is NULL,
- NULL is returned.
-
- Pointers passed as arguments into get_slot are the responsibility
- of the caller. Pointers returned by get_slot are owned by the
- kvp_frame. Make copies as needed.
- @{
-*/
-KvpValue * kvp_frame_get_slot(const KvpFrame * frame, const char * key);
-
-/** This routine return the value at the end of the
- * path, or NULL if any portion of the path doesn't exist.
- */
-KvpValue * kvp_frame_get_slot_path (KvpFrame *frame,
- const char *first_key, ...);
-
-/** This routine return the value at the end of the
- * path, or NULL if any portion of the path doesn't exist.
- */
-KvpValue * kvp_frame_get_slot_path_gslist (KvpFrame *frame,
- GSList *key_path);
-
-/**
- * Similar returns as strcmp.
- */
-gint kvp_frame_compare(const KvpFrame *fa, const KvpFrame *fb);
-
-gint double_compare(double v1, double v2);
-/** @} */
-/** @name KvpValue List Convenience Functions
-
- You probably shouldn't be using these low-level routines
-
- kvp_glist_compare() compares <b>GLists of kvp_values</b> (not to
- be confused with GLists of something else): it iterates over
- the list elements, performing a kvp_value_compare on each.
- @{
-*/
-gint kvp_glist_compare(const GList * list1, const GList * list2);
-
-/** kvp_glist_copy() performs a deep copy of a <b>GList of
- * kvp_values</b> (not to be confused with GLists of something
- * else): same as mapping kvp_value_copy() over the elements and
- * then copying the spine.
- */
-GList * kvp_glist_copy(const GList * list);
-
-/** kvp_glist_delete() performs a deep delete of a <b>GList of
- * kvp_values</b> (not to be confused with GLists of something
- * else): same as mapping * kvp_value_delete() over the elements
- * and then deleting the GList.
- */
-void kvp_glist_delete(GList * list);
-/** @} */
-
-
-/** @name KvpValue Constructors
-
- You probably shouldn't be using these low-level routines
-
- The following routines are constructors for kvp_value.
- Those with pointer arguments copy in the value.
- The *_nc() versions do *not* copy in thier values,
- but use them directly.
- @{
- */
-KvpValue * kvp_value_new_gint64(gint64 value);
-KvpValue * kvp_value_new_double(double value);
-
-/** \deprecated
-
-Use kvp_value_new_numeric instead of kvp_value_new_gnc_numeric
-*/
-#define kvp_value_new_gnc_numeric kvp_value_new_numeric
-KvpValue * kvp_value_new_numeric(gnc_numeric value);
-KvpValue * kvp_value_new_string(const char * value);
-KvpValue * kvp_value_new_guid(const GUID * guid);
-KvpValue * kvp_value_new_timespec(Timespec timespec);
-KvpValue * kvp_value_new_binary(const void * data, guint64 datasize);
-KvpValue * kvp_value_new_frame(const KvpFrame * value);
-
-/** Creates a KvpValue from a <b>GList of kvp_value's</b>! (Not to be
- * confused with GList's of something else!) */
-KvpValue * kvp_value_new_glist(const GList * value);
-
-/** value constructors (non-copying - KvpValue takes pointer ownership)
- values *must* have been allocated via glib allocators! (gnew, etc.) */
-KvpValue * kvp_value_new_binary_nc(void * data, guint64 datasize);
-
-/** Creates a KvpValue from a <b>GList of kvp_value's</b>! (Not to be
- * confused with GList's of something else!)
- *
- * This value constructor is non-copying (KvpValue takes pointer
- * ownership). The values *must* have been allocated via glib
- * allocators! (gnew, etc.) */
-KvpValue * kvp_value_new_glist_nc(GList *lst);
-
-/** value constructors (non-copying - KvpValue takes pointer ownership)
- values *must* have been allocated via glib allocators! (gnew, etc.) */
-KvpValue * kvp_value_new_frame_nc(KvpFrame * value);
-
-/** This is a deep (recursive) delete. */
-void kvp_value_delete(KvpValue * value);
-
-/** This is a deep value copy. */
-KvpValue * kvp_value_copy(const KvpValue * value);
-
-/** Replace old frame value with new, return old frame */
-KvpFrame * kvp_value_replace_frame_nc(KvpValue *value, KvpFrame * newframe);
-
-/** Replace old glist value with new, return old glist */
-GList * kvp_value_replace_glist_nc(KvpValue *value, GList *newlist);
-
-/** @} */
-
-
-/** @name KvpValue Value access
-
- You probably shouldn't be using these low-level routines
- @{
-*/
-
-KvpValueType kvp_value_get_type(const KvpValue * value);
-
-
-/** Value accessors. Those for GUID, binary, GList, KvpFrame and
- * string are non-copying -- the caller can modify the value
- * directly. Just don't free it, or you screw up everything.
- * Note that if another value is stored at the key location
- * that this value came from, then this value will be
- * uncermoniously deleted, and you will be left pointing to
- * garbage. So don't store values at the same time you are
- * examining their contents.
- */
-
-gint64 kvp_value_get_gint64(const KvpValue * value);
-double kvp_value_get_double(const KvpValue * value);
-gnc_numeric kvp_value_get_numeric(const KvpValue * value);
-
-/** Value accessor. This one is non-copying -- the caller can modify
- * the value directly. */
-char * kvp_value_get_string(const KvpValue * value);
-
-/** Value accessor. This one is non-copying -- the caller can modify
- * the value directly. */
-GUID * kvp_value_get_guid(const KvpValue * value);
-
-/** Value accessor. This one is non-copying -- the caller can modify
- * the value directly. */
-void * kvp_value_get_binary(const KvpValue * value,
- guint64 * size_return);
-
-/** Returns the GList of kvp_frame's (not to be confused with GList's
- * of something else!) from the given kvp_frame. This one is
- * non-copying -- the caller can modify the value directly. */
-GList * kvp_value_get_glist(const KvpValue * value);
-
-/** Value accessor. This one is non-copying -- the caller can modify
- * the value directly. */
-KvpFrame * kvp_value_get_frame(const KvpValue * value);
-Timespec kvp_value_get_timespec(const KvpValue * value);
-
-/**
- * Similar returns as strcmp.
- **/
-gint kvp_value_compare(const KvpValue *va, const KvpValue *vb);
-
-/** @} */
-
-/** \brief General purpose function to convert any KvpValue to a string.
-
-Only the bare string is returned, there is no debugging information.
-*/
-gchar* kvp_value_to_bare_string(const KvpValue *val);
-
-/** \brief Debug version of kvp_value_to_string
-
-This version is used only by ::qof_query_printValueForParam,
-itself a debugging and development utility function.
-*/
-gchar* kvp_value_to_string(const KvpValue *val);
-
-/** Manipulator:
- *
- * copying - but more efficient than creating a new KvpValue manually. */
-gboolean kvp_value_binary_append(KvpValue *v, void *data, guint64 size);
-
-/** @name Iterators
-@{
-*/
-/** Traverse all of the slots in the given kvp_frame. This function
- does not descend recursively to traverse any kvp_frames stored as
- slot values. You must handle that in proc, with a suitable
- recursive call if desired. */
-void kvp_frame_for_each_slot(KvpFrame *f,
- void (*proc)(const char *key,
- KvpValue *value,
- gpointer data),
- gpointer data);
-
-/** @} */
-
-/** Internal helper routines, you probably shouldn't be using these. */
-gchar* kvp_frame_to_string(const KvpFrame *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 KvpFrame *frame);
-
-/** @} */
-#endif
Deleted: gnucash/trunk/src/engine/md5.c
===================================================================
--- gnucash/trunk/src/engine/md5.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/md5.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,445 +0,0 @@
-/* md5.c - Functions to compute MD5 message digest of files or memory blocks
- according to the definition of MD5 in RFC 1321 from April 1992.
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
- NOTE: The canonical source of this file is maintained with the GNU C
- Library. Bugs can be reported to bug-glibc at prep.ai.mit.edu.
-
- 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, 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, write to the Free Software Foundation,
- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-/* Written by Ulrich Drepper <drepper at gnu.ai.mit.edu>, 1995. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <sys/types.h>
-
-#if STDC_HEADERS || defined _LIBC
-# include <stdlib.h>
-# include <string.h>
-#else
-# ifndef HAVE_MEMCPY
-#include <string.h>
-# define memcpy(d, s, n) bcopy ((s), (d), (n))
-# endif
-#endif
-
-#include "md5.h"
-
-#ifdef _LIBC
-# include <endian.h>
-# if __BYTE_ORDER == __BIG_ENDIAN
-# define WORDS_BIGENDIAN 1
-# endif
-#endif
-
-#ifdef WORDS_BIGENDIAN
-# define SWAP(n) \
- (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
-#else
-# define SWAP(n) (n)
-#endif
-
-
-/* This array contains the bytes used to pad the buffer to the next
- 64-byte boundary. (RFC 1321, 3.1: Step 1) */
-static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
-
-
-/* Initialize structure containing state of computation.
- (RFC 1321, 3.3: Step 3) */
-void
-md5_init_ctx (ctx)
- struct md5_ctx *ctx;
-{
- ctx->A = 0x67452301;
- ctx->B = 0xefcdab89;
- ctx->C = 0x98badcfe;
- ctx->D = 0x10325476;
-
- ctx->total[0] = ctx->total[1] = 0;
- ctx->buflen = 0;
-}
-
-/* Put result from CTX in first 16 bytes following RESBUF. The result
- must be in little endian byte order.
-
- IMPORTANT: On some systems it is required that RESBUF is correctly
- aligned for a 32 bits value. */
-void *
-md5_read_ctx (ctx, resbuf)
- const struct md5_ctx *ctx;
- void *resbuf;
-{
- ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
- ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
- ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
- ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
-
- return resbuf;
-}
-
-/* Process the remaining bytes in the internal buffer and the usual
- prolog according to the standard and write the result to RESBUF.
-
- IMPORTANT: On some systems it is required that RESBUF is correctly
- aligned for a 32 bits value. */
-void *
-md5_finish_ctx (ctx, resbuf)
- struct md5_ctx *ctx;
- void *resbuf;
-{
- /* Take yet unprocessed bytes into account. */
- md5_uint32 bytes = ctx->buflen;
- size_t pad;
-
- /* Now count remaining bytes. */
- ctx->total[0] += bytes;
- if (ctx->total[0] < bytes)
- ++ctx->total[1];
-
- pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
- memcpy (&ctx->buffer[bytes], fillbuf, pad);
-
- /* Put the 64-bit file length in *bits* at the end of the buffer. */
- *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3);
- *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) |
- (ctx->total[0] >> 29));
-
- /* Process last bytes. */
- md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
-
- return md5_read_ctx (ctx, resbuf);
-}
-
-/* Compute MD5 message digest for bytes read from STREAM. The
- resulting message digest number will be written into the 16 bytes
- beginning at RESBLOCK. */
-int
-md5_stream (stream, resblock)
- FILE *stream;
- void *resblock;
-{
- /* Important: BLOCKSIZE must be a multiple of 64. */
-#define BLOCKSIZE 4096
- struct md5_ctx ctx;
- char buffer[BLOCKSIZE + 72];
- size_t sum;
-
- /* Initialize the computation context. */
- md5_init_ctx (&ctx);
-
- /* Iterate over full file contents. */
- while (1)
- {
- /* We read the file in blocks of BLOCKSIZE bytes. One call of the
- computation function processes the whole buffer so that with the
- next round of the loop another block can be read. */
- size_t n;
- sum = 0;
-
- /* Read block. Take care for partial reads. */
- do
- {
- n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
-
- sum += n;
- }
- while (sum < BLOCKSIZE && n != 0);
- if (n == 0 && ferror (stream))
- return 1;
-
- /* If end of file is reached, end the loop. */
- if (n == 0)
- break;
-
- /* Process buffer with BLOCKSIZE bytes. Note that
- BLOCKSIZE % 64 == 0
- */
- md5_process_block (buffer, BLOCKSIZE, &ctx);
- }
-
- /* Add the last bytes if necessary. */
- if (sum > 0)
- md5_process_bytes (buffer, sum, &ctx);
-
- /* Construct result in desired memory. */
- md5_finish_ctx (&ctx, resblock);
- return 0;
-}
-
-/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
- result is always in little endian byte order, so that a byte-wise
- output yields to the wanted ASCII representation of the message
- digest. */
-void *
-md5_buffer (buffer, len, resblock)
- const char *buffer;
- size_t len;
- void *resblock;
-{
- struct md5_ctx ctx;
-
- /* Initialize the computation context. */
- md5_init_ctx (&ctx);
-
- /* Process whole buffer but last len % 64 bytes. */
- md5_process_bytes (buffer, len, &ctx);
-
- /* Put result in desired memory area. */
- return md5_finish_ctx (&ctx, resblock);
-}
-
-
-void
-md5_process_bytes (buffer, len, ctx)
- const void *buffer;
- size_t len;
- struct md5_ctx *ctx;
-{
-#define NUM_MD5_WORDS 1024
- size_t add = 0;
-
- /* When we already have some bits in our internal buffer concatenate
- both inputs first. */
- if (ctx->buflen != 0)
- {
- size_t left_over = ctx->buflen;
-
- add = 128 - left_over > len ? len : 128 - left_over;
-
- memcpy (&ctx->buffer[left_over], buffer, add);
- ctx->buflen += add;
-
- if (left_over + add > 64)
- {
- md5_process_block (ctx->buffer, (left_over + add) & ~63, ctx);
- /* The regions in the following copy operation cannot overlap. */
- memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
- (left_over + add) & 63);
- ctx->buflen = (left_over + add) & 63;
- }
-
- buffer = (const char *) buffer + add;
- len -= add;
- }
-
- /* Process available complete blocks. */
- if (len > 64)
- {
- if ((add & 3) == 0) /* buffer is still 32-bit aligned */
- {
- md5_process_block (buffer, len & ~63, ctx);
- buffer = (const char *) buffer + (len & ~63);
- }
- else /* buffer is not 32-bit aligned */
- {
- md5_uint32 md5_buffer[NUM_MD5_WORDS];
- size_t num_bytes;
- size_t buf_bytes;
-
- num_bytes = len & ~63;
- while (num_bytes > 0)
- {
- buf_bytes = (num_bytes < sizeof(md5_buffer)) ?
- num_bytes : sizeof(md5_buffer);
- memcpy (md5_buffer, buffer, buf_bytes);
- md5_process_block (md5_buffer, buf_bytes, ctx);
- num_bytes -= buf_bytes;
- buffer = (const char *) buffer + buf_bytes;
- }
- }
-
- len &= 63;
- }
-
- /* Move remaining bytes in internal buffer. */
- if (len > 0)
- {
- memcpy (ctx->buffer, buffer, len);
- ctx->buflen = len;
- }
-}
-
-
-/* These are the four functions used in the four steps of the MD5 algorithm
- and defined in the RFC 1321. The first function is a little bit optimized
- (as found in Colin Plumbs public domain implementation). */
-/* #define FF(b, c, d) ((b & c) | (~b & d)) */
-#define FF(b, c, d) (d ^ (b & (c ^ d)))
-#define FG(b, c, d) FF (d, b, c)
-#define FH(b, c, d) (b ^ c ^ d)
-#define FI(b, c, d) (c ^ (b | ~d))
-
-/* Process LEN bytes of BUFFER, accumulating context into CTX.
- It is assumed that LEN % 64 == 0. */
-
-void
-md5_process_block (buffer, len, ctx)
- const void *buffer;
- size_t len;
- struct md5_ctx *ctx;
-{
- md5_uint32 correct_words[16];
- const md5_uint32 *words = buffer;
- size_t nwords = len / sizeof (md5_uint32);
- const md5_uint32 *endp = words + nwords;
- md5_uint32 A = ctx->A;
- md5_uint32 B = ctx->B;
- md5_uint32 C = ctx->C;
- md5_uint32 D = ctx->D;
-
- /* First increment the byte count. RFC 1321 specifies the possible
- length of the file up to 2^64 bits. Here we only compute the
- number of bytes. Do a double word increment. */
- ctx->total[0] += len;
- if (ctx->total[0] < len)
- ++ctx->total[1];
-
- /* Process all bytes in the buffer with 64 bytes in each round of
- the loop. */
- while (words < endp)
- {
- md5_uint32 *cwp = correct_words;
- md5_uint32 A_save = A;
- md5_uint32 B_save = B;
- md5_uint32 C_save = C;
- md5_uint32 D_save = D;
-
- /* First round: using the given function, the context and a constant
- the next context is computed. Because the algorithms processing
- unit is a 32-bit word and it is determined to work on words in
- little endian byte order we perhaps have to change the byte order
- before the computation. To reduce the work for the next steps
- we store the swapped words in the array CORRECT_WORDS. */
-
-#define OP(a, b, c, d, s, T) \
- do \
- { \
- a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \
- ++words; \
- CYCLIC (a, s); \
- a += b; \
- } \
- while (0)
-
- /* It is unfortunate that C does not provide an operator for
- cyclic rotation. Hope the C compiler is smart enough. */
-#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
-
- /* Before we start, one word to the strange constants.
- They are defined in RFC 1321 as
-
- T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
- */
-
- /* Round 1. */
- OP (A, B, C, D, 7, 0xd76aa478);
- OP (D, A, B, C, 12, 0xe8c7b756);
- OP (C, D, A, B, 17, 0x242070db);
- OP (B, C, D, A, 22, 0xc1bdceee);
- OP (A, B, C, D, 7, 0xf57c0faf);
- OP (D, A, B, C, 12, 0x4787c62a);
- OP (C, D, A, B, 17, 0xa8304613);
- OP (B, C, D, A, 22, 0xfd469501);
- OP (A, B, C, D, 7, 0x698098d8);
- OP (D, A, B, C, 12, 0x8b44f7af);
- OP (C, D, A, B, 17, 0xffff5bb1);
- OP (B, C, D, A, 22, 0x895cd7be);
- OP (A, B, C, D, 7, 0x6b901122);
- OP (D, A, B, C, 12, 0xfd987193);
- OP (C, D, A, B, 17, 0xa679438e);
- OP (B, C, D, A, 22, 0x49b40821);
-
- /* For the second to fourth round we have the possibly swapped words
- in CORRECT_WORDS. Redefine the macro to take an additional first
- argument specifying the function to use. */
-#undef OP
-#define OP(f, a, b, c, d, k, s, T) \
- do \
- { \
- a += f (b, c, d) + correct_words[k] + T; \
- CYCLIC (a, s); \
- a += b; \
- } \
- while (0)
-
- /* Round 2. */
- OP (FG, A, B, C, D, 1, 5, 0xf61e2562);
- OP (FG, D, A, B, C, 6, 9, 0xc040b340);
- OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
- OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
- OP (FG, A, B, C, D, 5, 5, 0xd62f105d);
- OP (FG, D, A, B, C, 10, 9, 0x02441453);
- OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
- OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
- OP (FG, A, B, C, D, 9, 5, 0x21e1cde6);
- OP (FG, D, A, B, C, 14, 9, 0xc33707d6);
- OP (FG, C, D, A, B, 3, 14, 0xf4d50d87);
- OP (FG, B, C, D, A, 8, 20, 0x455a14ed);
- OP (FG, A, B, C, D, 13, 5, 0xa9e3e905);
- OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8);
- OP (FG, C, D, A, B, 7, 14, 0x676f02d9);
- OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
-
- /* Round 3. */
- OP (FH, A, B, C, D, 5, 4, 0xfffa3942);
- OP (FH, D, A, B, C, 8, 11, 0x8771f681);
- OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
- OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
- OP (FH, A, B, C, D, 1, 4, 0xa4beea44);
- OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9);
- OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60);
- OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
- OP (FH, A, B, C, D, 13, 4, 0x289b7ec6);
- OP (FH, D, A, B, C, 0, 11, 0xeaa127fa);
- OP (FH, C, D, A, B, 3, 16, 0xd4ef3085);
- OP (FH, B, C, D, A, 6, 23, 0x04881d05);
- OP (FH, A, B, C, D, 9, 4, 0xd9d4d039);
- OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
- OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
- OP (FH, B, C, D, A, 2, 23, 0xc4ac5665);
-
- /* Round 4. */
- OP (FI, A, B, C, D, 0, 6, 0xf4292244);
- OP (FI, D, A, B, C, 7, 10, 0x432aff97);
- OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
- OP (FI, B, C, D, A, 5, 21, 0xfc93a039);
- OP (FI, A, B, C, D, 12, 6, 0x655b59c3);
- OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92);
- OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
- OP (FI, B, C, D, A, 1, 21, 0x85845dd1);
- OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f);
- OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
- OP (FI, C, D, A, B, 6, 15, 0xa3014314);
- OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
- OP (FI, A, B, C, D, 4, 6, 0xf7537e82);
- OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
- OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
- OP (FI, B, C, D, A, 9, 21, 0xeb86d391);
-
- /* Add the starting values of the context. */
- A += A_save;
- B += B_save;
- C += C_save;
- D += D_save;
- }
-
- /* Put checksum in context given as argument. */
- ctx->A = A;
- ctx->B = B;
- ctx->C = C;
- ctx->D = D;
-}
Deleted: gnucash/trunk/src/engine/md5.h
===================================================================
--- gnucash/trunk/src/engine/md5.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/md5.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,163 +0,0 @@
-/* md5.h - Declaration of functions and data types used for MD5 sum
- computing library functions.
- Copyright (C) 1995, 1996 Free Software Foundation, Inc.
- NOTE: The canonical source of this file is maintained with the GNU C
- Library. Bugs can be reported to bug-glibc at prep.ai.mit.edu.
-
- 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, 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, write to the Free Software Foundation,
- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#ifndef _MD5_H
-#define _MD5_H 1
-
-#include <stddef.h>
-#include <stdio.h>
-
-#if defined HAVE_LIMITS_H || _LIBC
-# include <limits.h>
-#endif
-
-/* The following contortions are an attempt to use the C preprocessor
- to determine an unsigned integral type that is 32 bits wide. An
- alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
- doing that would require that the configure script compile and *run*
- the resulting executable. Locally running cross-compiled executables
- is usually not possible. */
-
-#ifdef _LIBC
-# include <sys/types.h>
-typedef u_int32_t md5_uint32;
-#else
-# if defined __STDC__ && __STDC__
-# define UINT_MAX_32_BITS 4294967295U
-# else
-# define UINT_MAX_32_BITS 0xFFFFFFFF
-# endif
-
-/* If UINT_MAX isn't defined, assume it's a 32-bit type.
- This should be valid for all systems GNU cares about because
- that doesn't include 16-bit systems, and only modern systems
- (that certainly have <limits.h>) have 64+-bit integral types. */
-
-# ifndef UINT_MAX
-# define UINT_MAX UINT_MAX_32_BITS
-# endif
-
-# if UINT_MAX == UINT_MAX_32_BITS
- typedef unsigned int md5_uint32;
-# else
-# if USHRT_MAX == UINT_MAX_32_BITS
- typedef unsigned short md5_uint32;
-# else
-# if ULONG_MAX == UINT_MAX_32_BITS
- typedef unsigned long md5_uint32;
-# else
- /* The following line is intended to evoke an error.
- Using #error is not portable enough. */
- "Cannot determine unsigned 32-bit data type."
-# endif
-# endif
-# endif
-#endif
-
-#undef __P
-#if defined (__STDC__) && __STDC__
-#define __P(x) x
-#else
-#define __P(x) ()
-#endif
-
-/* Structure to save state of computation between the single steps. */
-struct md5_ctx
-{
- md5_uint32 A;
- md5_uint32 B;
- md5_uint32 C;
- md5_uint32 D;
-
- md5_uint32 total[2];
- md5_uint32 buflen;
- char buffer[128];
-};
-
-/*
- * The following three functions are build up the low level used in
- * the functions `md5_stream' and `md5_buffer'.
- */
-
-/* Initialize structure containing state of computation.
- (RFC 1321, 3.3: Step 3) */
-extern void md5_init_ctx __P ((struct md5_ctx *ctx));
-
-
-/* Starting with the result of former calls of this function (or the
- initialization function update the context for the next LEN bytes
- starting at BUFFER.
-
- It is necessary that LEN is a multiple of 64!!!
-
- IMPORTANT: On some systems it is required that buffer be 32-bit
- aligned. */
-extern void md5_process_block __P ((const void *buffer, size_t len,
- struct md5_ctx *ctx));
-
-/* Starting with the result of former calls of this function (or the
- initialization function) update the context for the next LEN bytes
- starting at BUFFER.
-
- It is NOT required that LEN is a multiple of 64.
-
- IMPORTANT: On some systems it is required that buffer be 32-bit
- aligned. */
-extern void md5_process_bytes __P ((const void *buffer, size_t len,
- struct md5_ctx *ctx));
-
-/* Process the remaining bytes in the buffer and put result from CTX
- in first 16 bytes following RESBUF. The result is always in little
- endian byte order, so that a byte-wise output yields to the wanted
- ASCII representation of the message digest.
-
- IMPORTANT: On some systems it is required that RESBUF be correctly
- aligned for a 32 bits value. */
-extern void *md5_finish_ctx __P ((struct md5_ctx *ctx, void *resbuf));
-
-
-/* Put result from CTX in first 16 bytes following RESBUF. The result is
- always in little endian byte order, so that a byte-wise output yields
- to the wanted ASCII representation of the message digest.
-
- IMPORTANT: On some systems it is required that RESBUF be correctly
- aligned for a 32 bits value. */
-extern void *md5_read_ctx __P ((const struct md5_ctx *ctx, void *resbuf));
-
-
-/* Compute MD5 message digest for bytes read from STREAM. The
- resulting message digest number will be written into the 16 bytes
- beginning at RESBLOCK.
-
- IMPORTANT: On some systems it is required that resblock be 32-bit
- aligned. */
-extern int md5_stream __P ((FILE *stream, void *resblock));
-
-
-/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
- result is always in little endian byte order, so that a byte-wise
- output yields to the wanted ASCII representation of the message
- digest.
-
- IMPORTANT: On some systems it is required that buffer and resblock
- be correctly 32-bit aligned. */
-extern void *md5_buffer __P ((const char *buffer, size_t len, void *resblock));
-
-#endif
Deleted: gnucash/trunk/src/engine/qof-be-utils.h
===================================================================
--- gnucash/trunk/src/engine/qof-be-utils.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qof-be-utils.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,186 +0,0 @@
-/********************************************************************\
- * qof-be-utils.h: api for data storage backend *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-/** @addtogroup Object
- @{ */
-/** @addtogroup Backend
- @{ */
-/** @file qof-be-utils.h
- @brief QOF Backend Utilities
- @author Derek Atkins <derek at ihtfp.com>
- @author Neil Williams <linux at codehelp.co.uk>
-
- Common code used by objects to define begin_edit() and
- commit_edit() functions.
-
-*/
-
-#ifndef QOF_BE_UTILS_H
-#define QOF_BE_UTILS_H
-
-#include "gnc-trace.h"
-#include "gnc-engine-util.h"
-#include "qofbackend-p.h"
-#include "qofbook.h"
-#include "qofinstance.h"
-
-/** begin_edit helper
- *
- * @param inst: an instance of QofInstance
- *
- * The caller should use this macro first and then perform any other operations.
-
- Uses newly created functions to allow the macro to be used
- when QOF is linked as a library. qofbackend-p.h is a private header.
- */
-
-#define QOF_BEGIN_EDIT(inst) \
- QofBackend * be; \
- if (!(inst)) return; \
- \
- (inst)->editlevel++; \
- if (1 < (inst)->editlevel) return; \
- \
- if (0 >= (inst)->editlevel) \
- { \
- PERR ("unbalanced call - resetting (was %d)", (inst)->editlevel); \
- (inst)->editlevel = 1; \
- } \
- ENTER ("(inst=%p)", (inst)); \
- \
- /* See if there's a backend. If there is, invoke it. */ \
- be = qof_book_get_backend ((inst)->book); \
- if (be && qof_backend_begin_exists((be))) { \
- qof_backend_run_begin((be), (inst)); \
- } else { \
- /* We tried and failed to start transaction! */ \
- (inst)->dirty = TRUE; \
- } \
- LEAVE (" ");
-
-/** \brief function version of QOF_BEGIN_EDIT
-
-The macro cannot be used in a function that returns a value,
-this function can be used instead.
-*/
-gboolean qof_begin_edit(QofInstance *inst);
-
-/**
- * commit_edit helpers
- *
- * The caller should call PART1 as the first thing, then
- * perform any local operations prior to calling the backend.
- * Then call PART2.
- */
-
-/**
- * part1 -- deal with the editlevel
- *
- * @param inst: an instance of QofInstance
- */
-
-#define QOF_COMMIT_EDIT_PART1(inst) { \
- if (!(inst)) return; \
- \
- (inst)->editlevel--; \
- if (0 < (inst)->editlevel) return; \
- \
- /* The pricedb sufffers from delayed update... */ \
- /* This may be setting a bad precedent for other types, I fear. */ \
- /* Other types probably really should handle begin like this. */ \
- if ((-1 == (inst)->editlevel) && (inst)->dirty) \
- { \
- QofBackend * be; \
- be = qof_book_get_backend ((inst)->book); \
- if (be && qof_backend_begin_exists((be))) { \
- qof_backend_run_begin((be), (inst)); \
- } \
- (inst)->editlevel = 0; \
- } \
- if (0 > (inst)->editlevel) \
- { \
- PERR ("unbalanced call - resetting (was %d)", (inst)->editlevel); \
- (inst)->editlevel = 0; \
- } \
- ENTER ("(inst=%p) dirty=%d do-free=%d", \
- (inst), (inst)->dirty, (inst)->do_free); \
-}
-
-/** \brief function version of QOF_COMMIT_EDIT_PART1
-
-The macro cannot be used in a function that returns a value,
-this function can be used instead. Only Part1 is implemented.
-*/
-gboolean qof_commit_edit(QofInstance *inst);
-
-/**
- * part2 -- deal with the backend
- *
- * @param inst: an instance of QofInstance
- * @param on_error: a function called if there is a backend error.
- * void (*on_error)(inst, QofBackendError)
- * @param on_done: a function called after the commit is complete
- * but before the instect is freed. Perform any other
- * operations after the commit.
- * void (*on_done)(inst)
- * @param on_free: a function called if inst->do_free is TRUE.
- * void (*on_free)(inst)
- */
-#define QOF_COMMIT_EDIT_PART2(inst,on_error,on_done,on_free) { \
- QofBackend * be; \
- \
- /* See if there's a backend. If there is, invoke it. */ \
- be = qof_book_get_backend ((inst)->book); \
- if (be && qof_backend_commit_exists((be))) \
- { \
- QofBackendError errcode; \
- \
- /* clear errors */ \
- do { \
- errcode = qof_backend_get_error (be); \
- } while (ERR_BACKEND_NO_ERR != errcode); \
- \
- qof_backend_run_commit((be), (inst)); \
- errcode = qof_backend_get_error (be); \
- if (ERR_BACKEND_NO_ERR != errcode) \
- { \
- /* XXX Should perform a rollback here */ \
- (inst)->do_free = FALSE; \
- \
- /* Push error back onto the stack */ \
- qof_backend_set_error (be, errcode); \
- (on_error)((inst), errcode); \
- } \
- /* XXX the backend commit code should clear dirty!! */ \
- (inst)->dirty = FALSE; \
- } \
- (on_done)(inst); \
- \
- LEAVE ("inst=%p, dirty=%d do-free=%d", \
- (inst), (inst)->dirty, (inst)->do_free); \
- if ((inst)->do_free) { \
- (on_free)(inst); \
- return; \
- } \
-}
-
-#endif /* QOF_BE_UTILS_H */
-/** @} */
-/** @} */
Deleted: gnucash/trunk/src/engine/qof.h
===================================================================
--- gnucash/trunk/src/engine/qof.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qof.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,101 +0,0 @@
-/********************************************************************\
- * qof.h -- Master QOF public include file *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-#ifndef QOF_H_
-#define QOF_H_
-/** @defgroup QOF Query Object Framework
- @{
-*/
-
-/**
- @addtogroup Date Date: Date and Time Printing, Parsing and Manipulation
- @ingroup QOF
-*/
-/**
- @addtogroup Entity Entity: Types, Identity and Instance Framework
- @ingroup QOF
-
-*/
-/**
- @addtogroup KVP KVP: Key-Value Pairs
- @ingroup QOF
-*/
-/**
- @addtogroup Math128 Math128: 128-bit Integer Math Library
- @ingroup QOF
-*/
-/**
- @addtogroup Numeric Numeric: Rational Number Handling w/ Rounding Error Control
- @ingroup QOF
-*/
-/**
- @addtogroup Object Object: Dynamic Object Class Framework
- @ingroup QOF
-*/
-/** @addtogroup Choice Choice and collect : One to many links.
- @ingroup QOF
-*/
-/**
- @addtogroup Query Query: Querying for Objects
- @ingroup QOF
-*/
-/**
- @addtogroup Trace Trace: Error Reporting and Debugging
- @ingroup QOF
-*/
-/** @addtogroup BookMerge Merging QofBook structures
- @ingroup QOF
-*/
-/** @addtogroup Event Event: QOF event handlers.
- @ingroup QOF
-*/
-/**
- @addtogroup Utilities Misc Utilities
- @ingroup QOF
-*/
-/** @} */
-
-#include "qofid.h"
-#include "gnc-trace.h"
-#include "gnc-date.h"
-#include "gnc-numeric.h"
-#include "gnc-event.h"
-#include "gnc-engine-util.h"
-#include "guid.h"
-#include "kvp_frame.h"
-#include "kvp-util.h"
-#include "kvp-util-p.h"
-#include "qofbackend.h"
-#include "qofid-p.h"
-#include "qofinstance-p.h"
-#include "qofbook.h"
-#include "qofclass.h"
-#include "qofobject.h"
-#include "qofquery.h"
-#include "qofquerycore.h"
-#include "qofsession.h"
-#include "qofsql.h"
-#include "qofchoice.h"
-#include "qof_book_merge.h"
-#include "qof-be-utils.h"
-#include "qofla-dir.h"
-
-#endif /* QOF_H_ */
Deleted: gnucash/trunk/src/engine/qof_book_merge.c
===================================================================
--- gnucash/trunk/src/engine/qof_book_merge.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qof_book_merge.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,992 +0,0 @@
-/*********************************************************************
- * qof_book_merge.c -- api for QoFBook merge with collision handling *
- * Copyright (C) 2004-2005 Neil Williams <linux at codehelp.co.uk> *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
- ********************************************************************/
-
-#include "gnc-trace.h"
-#include "qof_book_merge.h"
-#include "qofinstance-p.h"
-#include "qofchoice.h"
-#include "qofid-p.h"
-
-static QofLogModule log_module = QOF_MOD_MERGE;
-
-/* private rule iteration struct */
-struct qof_book_mergeRuleIterate {
- qof_book_mergeRuleForeachCB fcn;
- qof_book_mergeData *data;
- qof_book_mergeRule *rule;
- GList *ruleList;
- guint remainder;
-};
-
-/* Make string type parameters 3 times more
- important in the match than default types.
- i.e. even if two other parameters differ,
- a string match will still provide a better target
- than when other types match and the string does not.
-*/
-#define DEFAULT_MERGE_WEIGHT 1
-#define QOF_STRING_WEIGHT 3
-#define QOF_DATE_STRING_LENGTH MAX_DATE_LENGTH
-
-static qof_book_mergeRule*
-qof_book_mergeUpdateRule(qof_book_mergeRule *currentRule, gboolean match, gint weight)
-{
- gboolean absolute;
-
- absolute = currentRule->mergeAbsolute;
- if(absolute && match && currentRule->mergeResult == MERGE_UNDEF) {
- currentRule->mergeResult = MERGE_ABSOLUTE;
- }
- if(absolute && !match) { currentRule->mergeResult = MERGE_UPDATE; }
- if(!absolute && match &¤tRule->mergeResult == MERGE_UNDEF) {
- currentRule->mergeResult = MERGE_DUPLICATE;
- }
- if(!absolute && !match) {
- currentRule->difference += weight;
- if(currentRule->mergeResult == MERGE_DUPLICATE) {
- currentRule->mergeResult = MERGE_REPORT;
- }
- }
- return currentRule;
-}
-
-struct collect_list_s
-{
- GSList *linkedEntList;
-};
-
-static void
-collect_reference_cb (QofEntity *ent, gpointer user_data)
-{
- struct collect_list_s *s;
-
- s = (struct collect_list_s*)user_data;
- if(!ent || !s) { return; }
- s->linkedEntList = g_slist_prepend(s->linkedEntList, ent);
-}
-
-static int
-qof_book_mergeCompare( qof_book_mergeData *mergeData )
-{
- qof_book_mergeRule *currentRule;
- QofCollection *mergeColl, *targetColl;
- gchar *stringImport, *stringTarget, *charImport, *charTarget;
- QofEntity *mergeEnt, *targetEnt, *referenceEnt;
- const GUID *guidImport, *guidTarget;
- QofParam *qtparam;
- KvpFrame *kvpImport, *kvpTarget;
- QofIdType mergeParamName;
- QofType mergeType;
- GSList *paramList;
- gboolean absolute, mergeError, knowntype, mergeMatch, booleanImport, booleanTarget,
- (*boolean_getter) (QofEntity*, QofParam*);
- Timespec tsImport, tsTarget, (*date_getter) (QofEntity*, QofParam*);
- gnc_numeric numericImport, numericTarget, (*numeric_getter) (QofEntity*, QofParam*);
- double doubleImport, doubleTarget, (*double_getter) (QofEntity*, QofParam*);
- gint32 i32Import, i32Target, (*int32_getter) (QofEntity*, QofParam*);
- gint64 i64Import, i64Target, (*int64_getter) (QofEntity*, QofParam*);
-
- g_return_val_if_fail((mergeData != NULL), -1);
- currentRule = mergeData->currentRule;
- g_return_val_if_fail((currentRule != NULL), -1);
- absolute = currentRule->mergeAbsolute;
- mergeEnt = currentRule->importEnt;
- targetEnt = currentRule->targetEnt;
- paramList = currentRule->mergeParam;
- currentRule->difference = 0;
- currentRule->mergeResult = MERGE_UNDEF;
- currentRule->linkedEntList = NULL;
- g_return_val_if_fail((targetEnt)||(mergeEnt)||(paramList), -1);
- kvpImport = kvp_frame_new();
- kvpTarget = kvp_frame_new();
- mergeError = FALSE;
- while(paramList != NULL) {
- mergeMatch = FALSE;
- knowntype = FALSE;
- qtparam = paramList->data;
- mergeParamName = qtparam->param_name;
- g_return_val_if_fail(mergeParamName != NULL, -1);
- mergeType = qtparam->param_type;
- if(safe_strcmp(mergeType, QOF_TYPE_STRING) == 0) {
- stringImport = qtparam->param_getfcn(mergeEnt,qtparam);
- stringTarget = qtparam->param_getfcn(targetEnt,qtparam);
- /* very strict string matches may need to be relaxed. */
- if(stringImport == NULL) { stringImport = ""; }
- if(stringTarget == NULL) { stringTarget = ""; }
- if(safe_strcmp(stringImport,stringTarget) == 0) { mergeMatch = TRUE; }
- /* Give special weight to a string match */
- currentRule = qof_book_mergeUpdateRule(currentRule, mergeMatch, QOF_STRING_WEIGHT);
- stringImport = stringTarget = NULL;
- knowntype= TRUE;
- }
- if(safe_strcmp(mergeType, QOF_TYPE_DATE) == 0) {
- date_getter = (Timespec (*)(QofEntity*, QofParam*))qtparam->param_getfcn;
- tsImport = date_getter(mergeEnt, qtparam);
- tsTarget = date_getter(targetEnt, qtparam);
- if(timespec_cmp(&tsImport, &tsTarget) == 0) { mergeMatch = TRUE; }
- currentRule = qof_book_mergeUpdateRule(currentRule, mergeMatch, DEFAULT_MERGE_WEIGHT);
- knowntype= TRUE;
- }
- if((safe_strcmp(mergeType, QOF_TYPE_NUMERIC) == 0) ||
- (safe_strcmp(mergeType, QOF_TYPE_DEBCRED) == 0)) {
- numeric_getter = (gnc_numeric (*)(QofEntity*, QofParam*)) qtparam->param_getfcn;
- numericImport = numeric_getter(mergeEnt,qtparam);
- numericTarget = numeric_getter(targetEnt,qtparam);
- if(gnc_numeric_compare (numericImport, numericTarget) == 0) { mergeMatch = TRUE; }
- currentRule = qof_book_mergeUpdateRule(currentRule, mergeMatch, DEFAULT_MERGE_WEIGHT);
- knowntype= TRUE;
- }
- if(safe_strcmp(mergeType, QOF_TYPE_GUID) == 0) {
- guidImport = qtparam->param_getfcn(mergeEnt,qtparam);
- guidTarget = qtparam->param_getfcn(targetEnt,qtparam);
- if(guid_compare(guidImport, guidTarget) == 0) { mergeMatch = TRUE; }
- currentRule = qof_book_mergeUpdateRule(currentRule, mergeMatch, DEFAULT_MERGE_WEIGHT);
- knowntype= TRUE;
- }
- if(safe_strcmp(mergeType, QOF_TYPE_INT32) == 0) {
- int32_getter = (gint32 (*)(QofEntity*, QofParam*)) qtparam->param_getfcn;
- i32Import = int32_getter(mergeEnt, qtparam);
- i32Target = int32_getter(targetEnt, qtparam);
- if(i32Target == i32Import) { mergeMatch = TRUE; }
- currentRule = qof_book_mergeUpdateRule(currentRule, mergeMatch, DEFAULT_MERGE_WEIGHT);
- knowntype= TRUE;
- }
- if(safe_strcmp(mergeType, QOF_TYPE_INT64) == 0) {
- int64_getter = (gint64 (*)(QofEntity*, QofParam*)) qtparam->param_getfcn;
- i64Import = int64_getter(mergeEnt, qtparam);
- i64Target = int64_getter(targetEnt, qtparam);
- if(i64Target == i64Import) { mergeMatch = TRUE; }
- currentRule = qof_book_mergeUpdateRule(currentRule, mergeMatch, DEFAULT_MERGE_WEIGHT);
- knowntype= TRUE;
- }
- if(safe_strcmp(mergeType, QOF_TYPE_DOUBLE) == 0) {
- double_getter = (double (*)(QofEntity*, QofParam*)) qtparam->param_getfcn;
- doubleImport = double_getter(mergeEnt, qtparam);
- doubleTarget = double_getter(mergeEnt, qtparam);
- if(doubleImport == doubleTarget) { mergeMatch = TRUE; }
- currentRule = qof_book_mergeUpdateRule(currentRule, mergeMatch, DEFAULT_MERGE_WEIGHT);
- knowntype= TRUE;
- }
- if(safe_strcmp(mergeType, QOF_TYPE_BOOLEAN) == 0){
- boolean_getter = (gboolean (*)(QofEntity*, QofParam*)) qtparam->param_getfcn;
- booleanImport = boolean_getter(mergeEnt, qtparam);
- booleanTarget = boolean_getter(targetEnt, qtparam);
- if(booleanImport != FALSE && booleanImport != TRUE) { booleanImport = FALSE; }
- if(booleanTarget != FALSE && booleanTarget != TRUE) { booleanTarget = FALSE; }
- if(booleanImport == booleanTarget) { mergeMatch = TRUE; }
- currentRule = qof_book_mergeUpdateRule(currentRule, mergeMatch, DEFAULT_MERGE_WEIGHT);
- knowntype= TRUE;
- }
- if(safe_strcmp(mergeType, QOF_TYPE_KVP) == 0) {
- kvpImport = kvp_frame_copy(qtparam->param_getfcn(mergeEnt,qtparam));
- kvpTarget = kvp_frame_copy(qtparam->param_getfcn(targetEnt,qtparam));
- if(kvp_frame_compare(kvpImport, kvpTarget) == 0) { mergeMatch = TRUE; }
- currentRule = qof_book_mergeUpdateRule(currentRule, mergeMatch, DEFAULT_MERGE_WEIGHT);
- knowntype= TRUE;
- }
- if(safe_strcmp(mergeType, QOF_TYPE_CHAR) == 0) {
- charImport = qtparam->param_getfcn(mergeEnt,qtparam);
- charTarget = qtparam->param_getfcn(targetEnt,qtparam);
- if(charImport == charTarget) { mergeMatch = TRUE; }
- currentRule = qof_book_mergeUpdateRule(currentRule, mergeMatch, DEFAULT_MERGE_WEIGHT);
- knowntype= TRUE;
- }
- /* No object should have QofSetterFunc defined for the book, but just to be safe, do nothing. */
- if(safe_strcmp(mergeType, QOF_ID_BOOK) == 0) { knowntype= TRUE; }
- if(safe_strcmp(mergeType, QOF_TYPE_COLLECT) == 0) {
- struct collect_list_s s;
- s.linkedEntList = NULL;
- mergeColl = qtparam->param_getfcn(mergeEnt, qtparam);
- targetColl = qtparam->param_getfcn(targetEnt, qtparam);
- s.linkedEntList = g_slist_copy(currentRule->linkedEntList);
- qof_collection_foreach(mergeColl, collect_reference_cb, &s);
- currentRule->linkedEntList = g_slist_copy(s.linkedEntList);
- if(0 == qof_collection_compare(mergeColl, targetColl)) { mergeMatch = TRUE; }
- currentRule = qof_book_mergeUpdateRule(currentRule, mergeMatch, DEFAULT_MERGE_WEIGHT);
- knowntype = TRUE;
- }
- if(safe_strcmp(mergeType, QOF_TYPE_CHOICE) ==0) {
- referenceEnt = qtparam->param_getfcn(mergeEnt, qtparam);
- currentRule->linkedEntList = g_slist_prepend(currentRule->linkedEntList, referenceEnt);
- if(referenceEnt == qtparam->param_getfcn(targetEnt, qtparam)) { mergeMatch = TRUE; }
- knowntype = TRUE;
- }
- if(knowntype == FALSE) {
- referenceEnt = qtparam->param_getfcn(mergeEnt, qtparam);
- if((referenceEnt != NULL)
- &&(safe_strcmp(referenceEnt->e_type, mergeType) == 0)) {
- currentRule->linkedEntList = g_slist_prepend(currentRule->linkedEntList, referenceEnt);
- if(referenceEnt == qtparam->param_getfcn(targetEnt, qtparam)) { mergeMatch = TRUE; }
- currentRule = qof_book_mergeUpdateRule(currentRule, mergeMatch, DEFAULT_MERGE_WEIGHT);
- }
- }
- paramList = g_slist_next(paramList);
- }
- mergeData->currentRule = currentRule;
- g_free(kvpImport);
- g_free(kvpTarget);
- return 0;
-}
-
-static void
-qof_book_mergeCommitForeachCB(gpointer rule, gpointer arg)
-{
- struct qof_book_mergeRuleIterate *iter;
-
- g_return_if_fail(arg != NULL);
- iter = (struct qof_book_mergeRuleIterate*)arg;
- g_return_if_fail(iter->data != NULL);
- iter->fcn (iter->data, (qof_book_mergeRule*)rule, iter->remainder);
- iter->remainder--;
-}
-
-static void
-qof_book_mergeCommitForeach (
- qof_book_mergeRuleForeachCB cb,
- qof_book_mergeResult mergeResult,
- qof_book_mergeData *mergeData)
-{
- struct qof_book_mergeRuleIterate iter;
- qof_book_mergeRule *currentRule;
- GList *subList;
-
- g_return_if_fail(cb != NULL);
- g_return_if_fail(mergeData != NULL);
- currentRule = mergeData->currentRule;
- g_return_if_fail(currentRule != NULL);
- g_return_if_fail(mergeResult > 0);
- g_return_if_fail((mergeResult != MERGE_INVALID)||(mergeResult != MERGE_UNDEF)||(mergeResult != MERGE_REPORT));
-
- iter.fcn = cb;
- subList = NULL;
- iter.ruleList = g_list_copy(mergeData->mergeList);
- while(iter.ruleList!=NULL) {
- currentRule = iter.ruleList->data;
- if(currentRule->mergeResult == mergeResult) {
- subList = g_list_prepend(subList, currentRule);
- }
- iter.ruleList = g_list_next(iter.ruleList);
- }
- iter.remainder = g_list_length(subList);
- iter.data = mergeData;
- g_list_foreach (subList, qof_book_mergeCommitForeachCB, &iter);
-}
-
-/* build the table of target comparisons
-
-This can get confusing, so bear with me. (!)
-
-Whilst iterating through the entities in the mergeBook, qof_book_mergeForeach assigns
-a targetEnt to each mergeEnt (until it runs out of targetEnt or mergeEnt). Each match
-is made against the one targetEnt that best matches the mergeEnt. Fine so far.
-
-Any mergeEnt is only ever assigned a targetEnt if the calculated difference between
-the two is less than the difference between that targetEnt and any previous mergeEnt
-match.
-
-The next mergeEnt may be a much better match for that targetEnt and the target_table
-is designed to solve the issues that result from this conflict. The previous match
-must be re-assigned because if two mergeEnt's are matched with only one targetEnt,
-data loss \b WILL follow. Equally, the current mergeEnt must replace the previous
-one as it is a better match. qof_entity_rating holds the details required to identify
-the correct mergeEnt to be re-assigned and these mergeEnt entities are therefore
-orphaned - to be re-matched later.
-
-Meanwhile, the current mergeEnt is entered into target_table with it's difference and
-rule data, in case an even better match is found later in the mergeBook.
-
-Finally, each mergeEnt in the orphan_list is now put through the comparison again.
-
-*/
-static gboolean
-qof_book_merge_rule_cmp(gconstpointer a, gconstpointer b)
-{
- qof_book_mergeRule *ra = (qof_book_mergeRule *) a;
- qof_book_mergeRule *rb = (qof_book_mergeRule *) b;
- if (ra->difference == rb->difference) { return TRUE; }
- else return FALSE;
-}
-
-static void
-qof_book_merge_orphan_check(double difference, qof_book_mergeRule *mergeRule, qof_book_mergeData *mergeData)
-{
- /* Called when difference is lower than previous
- Lookup target to find previous match
- and re-assign mergeEnt to orphan_list */
- qof_book_mergeRule *rule;
-
- g_return_if_fail(mergeRule != NULL);
- g_return_if_fail(mergeData != NULL);
- if(g_hash_table_size(mergeData->target_table) == 0) { return; }
- rule = (qof_book_mergeRule*)g_hash_table_lookup(mergeData->target_table, mergeRule->targetEnt);
- /* If NULL, no match was found. */
- if(rule == NULL) { return; }
- /* Only orphan if this is a better match than already exists. */
- if(difference >= rule->difference) { return; }
- rule->targetEnt = NULL;
- rule->mergeResult = MERGE_UNDEF;
- mergeData->orphan_list = g_slist_append(mergeData->orphan_list, rule);
-}
-
-static void
-qof_book_merge_match_orphans(qof_book_mergeData *mergeData)
-{
- GSList *orphans, *targets;
- qof_book_mergeRule *rule, *currentRule;
- QofEntity *best_matchEnt;
- double difference;
-
- g_return_if_fail(mergeData != NULL);
- currentRule = mergeData->currentRule;
- g_return_if_fail(currentRule != NULL);
- /* This routine does NOT copy the orphan list, it
- is used recursively until empty. */
- orphans = mergeData->orphan_list;
- targets = g_slist_copy(mergeData->targetList);
- while(orphans != NULL) {
- rule = orphans->data;
- g_return_if_fail(rule != NULL);
- difference = g_slist_length(mergeData->mergeObjectParams);
- if(rule->targetEnt == NULL) {
- rule->mergeResult = MERGE_NEW;
- rule->difference = 0;
- mergeData->mergeList = g_list_prepend(mergeData->mergeList,rule);
- orphans = g_slist_next(orphans);
- continue;
- }
- mergeData->currentRule = rule;
- g_return_if_fail(qof_book_mergeCompare(mergeData) != -1);
- if(difference > mergeData->currentRule->difference) {
- best_matchEnt = currentRule->targetEnt;
- difference = currentRule->difference;
- rule = currentRule;
- mergeData->mergeList = g_list_prepend(mergeData->mergeList,rule);
- qof_book_merge_orphan_check(difference, rule, mergeData);
- }
- orphans = g_slist_next(orphans);
- }
- g_slist_free(mergeData->orphan_list);
- g_slist_free(targets);
-}
-
-static void
-qof_book_mergeForeachTarget (QofEntity* targetEnt, gpointer user_data)
-{
- qof_book_mergeData *mergeData;
-
- g_return_if_fail(user_data != NULL);
- mergeData = (qof_book_mergeData*)user_data;
- g_return_if_fail(targetEnt != NULL);
- mergeData->targetList = g_slist_prepend(mergeData->targetList,targetEnt);
-}
-
-static void
-qof_book_mergeForeachTypeTarget ( QofObject* merge_obj, gpointer user_data)
-{
- qof_book_mergeData *mergeData;
- qof_book_mergeRule *currentRule;
-
- g_return_if_fail(user_data != NULL);
- mergeData = (qof_book_mergeData*)user_data;
- currentRule = mergeData->currentRule;
- g_return_if_fail(currentRule != NULL);
- g_return_if_fail(merge_obj != NULL);
- if(safe_strcmp(merge_obj->e_type, currentRule->importEnt->e_type) == 0) {
- qof_object_foreach(currentRule->importEnt->e_type, mergeData->targetBook,
- qof_book_mergeForeachTarget, user_data);
- }
-}
-
-static void
-qof_book_mergeForeach ( QofEntity* mergeEnt, gpointer user_data)
-{
- qof_book_mergeRule *mergeRule, *currentRule;
- qof_book_mergeData *mergeData;
- QofEntity *targetEnt, *best_matchEnt;
- GUID *g;
- double difference;
- GSList *c;
-
- g_return_if_fail(user_data != NULL);
- mergeData = (qof_book_mergeData*)user_data;
- g_return_if_fail(mergeEnt != NULL);
- currentRule = mergeData->currentRule;
- g_return_if_fail(currentRule != NULL);
- g = guid_malloc();
- *g = mergeEnt->guid;
- mergeRule = g_new(qof_book_mergeRule,1);
- mergeRule->importEnt = mergeEnt;
- mergeRule->difference = difference = 0;
- mergeRule->mergeAbsolute = FALSE;
- mergeRule->mergeResult = MERGE_UNDEF;
- mergeRule->updated = FALSE;
- mergeRule->mergeType = mergeEnt->e_type;
- mergeRule->mergeLabel = qof_object_get_type_label(mergeEnt->e_type);
- mergeRule->mergeParam = g_slist_copy(mergeData->mergeObjectParams);
- mergeRule->linkedEntList = NULL;
- mergeData->currentRule = mergeRule;
- targetEnt = best_matchEnt = NULL;
- targetEnt = qof_collection_lookup_entity (
- qof_book_get_collection (mergeData->targetBook, mergeEnt->e_type), g);
- if( targetEnt != NULL) {
- mergeRule->mergeAbsolute = TRUE;
- mergeRule->targetEnt = targetEnt;
- g_return_if_fail(qof_book_mergeCompare(mergeData) != -1);
- mergeRule->linkedEntList = g_slist_copy(currentRule->linkedEntList);
- mergeData->mergeList = g_list_prepend(mergeData->mergeList,mergeRule);
- return;
- }
- /* no absolute match exists */
- g_slist_free(mergeData->targetList);
- mergeData->targetList = NULL;
- qof_object_foreach_type(qof_book_mergeForeachTypeTarget, mergeData);
- if(g_slist_length(mergeData->targetList) == 0) {
- mergeRule->mergeResult = MERGE_NEW;
- }
- difference = g_slist_length(mergeRule->mergeParam);
- c = g_slist_copy(mergeData->targetList);
- while(c != NULL) {
- mergeRule->targetEnt = c->data;
- currentRule = mergeRule;
- /* compare two entities and sum the differences */
- g_return_if_fail(qof_book_mergeCompare(mergeData) != -1);
- if(mergeRule->difference == 0) {
- /* check if this is a better match than one already assigned */
- best_matchEnt = mergeRule->targetEnt;
- mergeRule->mergeResult = MERGE_DUPLICATE;
- difference = 0;
- mergeRule->linkedEntList = g_slist_copy(currentRule->linkedEntList);
- g_slist_free(c);
- guid_free(g);
- /* exact match, return */
- return;
- }
- if(difference > mergeRule->difference) {
- /* The chosen targetEnt determines the parenting of any child object */
- /* check if this is a better match than one already assigned */
- best_matchEnt = mergeRule->targetEnt;
- difference = mergeRule->difference;
- /* Use match to lookup the previous entity that matched this targetEnt (if any)
- and remove targetEnt from the rule for that mergeEnt.
- Add the previous mergeEnt to orphan_list.
- */
- qof_book_merge_orphan_check(difference, mergeRule, mergeData);
- }
- c = g_slist_next(c);
- }
- g_slist_free(c);
- if(best_matchEnt != NULL ) {
- mergeRule->targetEnt = best_matchEnt;
- mergeRule->difference = difference;
- /* Set this entity in the target_table in case a better match can be made
- with the next mergeEnt. */
- g_hash_table_insert(mergeData->target_table, mergeRule->targetEnt, mergeRule);
- /* compare again with the best partial match */
- g_return_if_fail(qof_book_mergeCompare(mergeData) != -1);
- mergeRule->linkedEntList = g_slist_copy(currentRule->linkedEntList);
- }
- else {
- mergeRule->targetEnt = NULL;
- mergeRule->difference = 0;
- mergeRule->mergeResult = MERGE_NEW;
- mergeRule->linkedEntList = g_slist_copy(currentRule->linkedEntList);
- }
- mergeData->mergeList = g_list_prepend(mergeData->mergeList,mergeRule);
- guid_free(g);
- /* return to qof_book_mergeInit */
-}
-
-static void
-qof_book_mergeForeachParam( QofParam* param, gpointer user_data)
-{
- qof_book_mergeData *mergeData;
-
- g_return_if_fail(user_data != NULL);
- mergeData = (qof_book_mergeData*)user_data;
- g_return_if_fail(param != NULL);
- if((param->param_getfcn != NULL)&&(param->param_setfcn != NULL)) {
- mergeData->mergeObjectParams = g_slist_append(mergeData->mergeObjectParams, param);
- }
-}
-
-static void
-qof_book_mergeForeachType ( QofObject* merge_obj, gpointer user_data)
-{
- qof_book_mergeData *mergeData;
-
- g_return_if_fail(user_data != NULL);
- mergeData = (qof_book_mergeData*)user_data;
- g_return_if_fail((merge_obj != NULL));
- /* Skip unsupported objects */
- if((merge_obj->create == NULL)||(merge_obj->foreach == NULL)){
- DEBUG (" merge_obj QOF support failed %s", merge_obj->e_type);
- return;
- }
- if(mergeData->mergeObjectParams != NULL) g_slist_free(mergeData->mergeObjectParams);
- mergeData->mergeObjectParams = NULL;
- qof_class_param_foreach(merge_obj->e_type, qof_book_mergeForeachParam , mergeData);
- qof_object_foreach(merge_obj->e_type, mergeData->mergeBook, qof_book_mergeForeach, mergeData);
-}
-
-static void
-qof_book_mergeRuleCB(gpointer rule, gpointer arg)
-{
- struct qof_book_mergeRuleIterate *iter;
- qof_book_mergeData *mergeData;
-
- g_return_if_fail(arg != NULL);
- iter = (struct qof_book_mergeRuleIterate*)arg;
- mergeData = iter->data;
- g_return_if_fail(mergeData != NULL);
- g_return_if_fail(mergeData->abort == FALSE);
- iter->fcn (mergeData, (qof_book_mergeRule*)rule, iter->remainder);
- iter->data = mergeData;
- iter->remainder--;
-}
-
-static void
-qof_book_mergeCommitRuleLoop(
- qof_book_mergeData *mergeData,
- qof_book_mergeRule *rule,
- guint remainder)
-{
- QofInstance *inst;
- gboolean registered_type;
- QofEntity *referenceEnt;
- /* cm_ prefix used for variables that hold the data to commit */
- QofCollection *cm_coll;
- QofParam *cm_param;
- gchar *cm_string;
- const GUID *cm_guid;
- KvpFrame *cm_kvp;
- /* function pointers and variables for parameter getters that don't use pointers normally */
- gnc_numeric cm_numeric, (*numeric_getter) (QofEntity*, QofParam*);
- double cm_double, (*double_getter) (QofEntity*, QofParam*);
- gboolean cm_boolean, (*boolean_getter) (QofEntity*, QofParam*);
- gint32 cm_i32, (*int32_getter) (QofEntity*, QofParam*);
- gint64 cm_i64, (*int64_getter) (QofEntity*, QofParam*);
- Timespec cm_date, (*date_getter) (QofEntity*, QofParam*);
- char cm_char, (*char_getter) (QofEntity*, QofParam*);
- /* function pointers to the parameter setters */
- void (*string_setter) (QofEntity*, const char*);
- void (*date_setter) (QofEntity*, Timespec);
- void (*numeric_setter) (QofEntity*, gnc_numeric);
- void (*guid_setter) (QofEntity*, const GUID*);
- void (*double_setter) (QofEntity*, double);
- void (*boolean_setter) (QofEntity*, gboolean);
- void (*i32_setter) (QofEntity*, gint32);
- void (*i64_setter) (QofEntity*, gint64);
- void (*char_setter) (QofEntity*, char);
- void (*kvp_frame_setter) (QofEntity*, KvpFrame*);
- void (*reference_setter) (QofEntity*, QofEntity*);
- void (*collection_setter)(QofEntity*, QofCollection*);
-
- g_return_if_fail(rule != NULL);
- g_return_if_fail(mergeData != NULL);
- g_return_if_fail(mergeData->targetBook != NULL);
- g_return_if_fail((rule->mergeResult != MERGE_NEW)||(rule->mergeResult != MERGE_UPDATE));
- /* create a new object for MERGE_NEW */
- /* The new object takes the GUID from the import to retain an absolute match */
- if(rule->mergeResult == MERGE_NEW) {
- inst = (QofInstance*)qof_object_new_instance(rule->importEnt->e_type, mergeData->targetBook);
- g_return_if_fail(inst != NULL);
- rule->targetEnt = &inst->entity;
- qof_entity_set_guid(rule->targetEnt, qof_entity_get_guid(rule->importEnt));
- }
- /* currentRule->targetEnt is now set,
- 1. by an absolute GUID match or
- 2. by best_matchEnt and difference or
- 3. by MERGE_NEW.
- */
- while(rule->mergeParam != NULL) {
- registered_type = FALSE;
- g_return_if_fail(rule->mergeParam->data);
- cm_param = rule->mergeParam->data;
- rule->mergeType = cm_param->param_type;
- if(safe_strcmp(rule->mergeType, QOF_TYPE_STRING) == 0) {
- cm_string = cm_param->param_getfcn(rule->importEnt, cm_param);
- string_setter = (void(*)(QofEntity*, const char*))cm_param->param_setfcn;
- if(string_setter != NULL) { string_setter(rule->targetEnt, cm_string); }
- registered_type = TRUE;
- }
- if(safe_strcmp(rule->mergeType, QOF_TYPE_DATE) == 0) {
- date_getter = (Timespec (*)(QofEntity*, QofParam*))cm_param->param_getfcn;
- cm_date = date_getter(rule->importEnt, cm_param);
- date_setter = (void(*)(QofEntity*, Timespec))cm_param->param_setfcn;
- if(date_setter != NULL) { date_setter(rule->targetEnt, cm_date); }
- registered_type = TRUE;
- }
- if((safe_strcmp(rule->mergeType, QOF_TYPE_NUMERIC) == 0) ||
- (safe_strcmp(rule->mergeType, QOF_TYPE_DEBCRED) == 0)) {
- numeric_getter = (gnc_numeric (*)(QofEntity*, QofParam*))cm_param->param_getfcn;
- cm_numeric = numeric_getter(rule->importEnt, cm_param);
- numeric_setter = (void(*)(QofEntity*, gnc_numeric))cm_param->param_setfcn;
- if(numeric_setter != NULL) { numeric_setter(rule->targetEnt, cm_numeric); }
- registered_type = TRUE;
- }
- if(safe_strcmp(rule->mergeType, QOF_TYPE_GUID) == 0) {
- cm_guid = cm_param->param_getfcn(rule->importEnt, cm_param);
- guid_setter = (void(*)(QofEntity*, const GUID*))cm_param->param_setfcn;
- if(guid_setter != NULL) { guid_setter(rule->targetEnt, cm_guid); }
- registered_type = TRUE;
- }
- if(safe_strcmp(rule->mergeType, QOF_TYPE_INT32) == 0) {
- int32_getter = (gint32 (*)(QofEntity*, QofParam*)) cm_param->param_getfcn;
- cm_i32 = int32_getter(rule->importEnt, cm_param);
- i32_setter = (void(*)(QofEntity*, gint32))cm_param->param_setfcn;
- if(i32_setter != NULL) { i32_setter(rule->targetEnt, cm_i32); }
- registered_type = TRUE;
- }
- if(safe_strcmp(rule->mergeType, QOF_TYPE_INT64) == 0) {
- int64_getter = (gint64 (*)(QofEntity*, QofParam*)) cm_param->param_getfcn;
- cm_i64 = int64_getter(rule->importEnt, cm_param);
- i64_setter = (void(*)(QofEntity*, gint64))cm_param->param_setfcn;
- if(i64_setter != NULL) { i64_setter(rule->targetEnt, cm_i64); }
- registered_type = TRUE;
- }
- if(safe_strcmp(rule->mergeType, QOF_TYPE_DOUBLE) == 0) {
- double_getter = (double (*)(QofEntity*, QofParam*)) cm_param->param_getfcn;
- cm_double = double_getter(rule->importEnt, cm_param);
- double_setter = (void(*)(QofEntity*, double))cm_param->param_setfcn;
- if(double_setter != NULL) { double_setter(rule->targetEnt, cm_double); }
- registered_type = TRUE;
- }
- if(safe_strcmp(rule->mergeType, QOF_TYPE_BOOLEAN) == 0){
- boolean_getter = (gboolean (*)(QofEntity*, QofParam*)) cm_param->param_getfcn;
- cm_boolean = boolean_getter(rule->importEnt, cm_param);
- boolean_setter = (void(*)(QofEntity*, gboolean))cm_param->param_setfcn;
- if(boolean_setter != NULL) { boolean_setter(rule->targetEnt, cm_boolean); }
- registered_type = TRUE;
- }
- if(safe_strcmp(rule->mergeType, QOF_TYPE_KVP) == 0) {
- cm_kvp = kvp_frame_copy(cm_param->param_getfcn(rule->importEnt,cm_param));
- kvp_frame_setter = (void(*)(QofEntity*, KvpFrame*))cm_param->param_setfcn;
- if(kvp_frame_setter != NULL) { kvp_frame_setter(rule->targetEnt, cm_kvp); }
- registered_type = TRUE;
- }
- if(safe_strcmp(rule->mergeType, QOF_TYPE_CHAR) == 0) {
- char_getter = (char (*)(QofEntity*, QofParam*)) cm_param->param_getfcn;
- cm_char = char_getter(rule->importEnt,cm_param);
- char_setter = (void(*)(QofEntity*, char))cm_param->param_setfcn;
- if(char_setter != NULL) { char_setter(rule->targetEnt, cm_char); }
- registered_type = TRUE;
- }
- if(safe_strcmp(rule->mergeType, QOF_TYPE_COLLECT) == 0) {
- cm_coll = cm_param->param_getfcn(rule->importEnt, cm_param);
- collection_setter = (void(*)(QofEntity*, QofCollection*))cm_param->param_setfcn;
- if(collection_setter != NULL) { collection_setter(rule->targetEnt, cm_coll); }
- registered_type = TRUE;
- }
- if(safe_strcmp(rule->mergeType, QOF_TYPE_CHOICE) == 0) {
- referenceEnt = cm_param->param_getfcn(rule->importEnt, cm_param);
- reference_setter = (void(*)(QofEntity*, QofEntity*))cm_param->param_setfcn;
- if(reference_setter != NULL)
- {
- reference_setter(rule->targetEnt, referenceEnt);
- }
- registered_type = TRUE;
- }
- if(registered_type == FALSE) {
- referenceEnt = cm_param->param_getfcn(rule->importEnt, cm_param);
- if(referenceEnt) {
- reference_setter = (void(*)(QofEntity*, QofEntity*))cm_param->param_setfcn;
- if(reference_setter != NULL)
- {
- reference_setter(rule->targetEnt, referenceEnt);
- }
- }
- }
- rule->mergeParam = g_slist_next(rule->mergeParam);
- }
-}
-/* ================================================================ */
-/* API functions. */
-
-qof_book_mergeData*
-qof_book_mergeInit( QofBook *importBook, QofBook *targetBook)
-{
- qof_book_mergeData *mergeData;
- qof_book_mergeRule *currentRule;
- GList *check;
-
- g_return_val_if_fail((importBook != NULL)&&(targetBook != NULL), NULL);
- mergeData = g_new(qof_book_mergeData, 1);
- mergeData->abort = FALSE;
- mergeData->mergeList = NULL;
- mergeData->targetList = NULL;
- mergeData->mergeBook = importBook;
- mergeData->targetBook = targetBook;
- mergeData->mergeObjectParams = NULL;
- mergeData->orphan_list = NULL;
- mergeData->target_table = g_hash_table_new( g_direct_hash, qof_book_merge_rule_cmp);
- currentRule = g_new(qof_book_mergeRule, 1);
- mergeData->currentRule = currentRule;
- qof_object_foreach_type(qof_book_mergeForeachType, mergeData);
- g_return_val_if_fail(mergeData->mergeObjectParams, NULL);
- if(mergeData->orphan_list != NULL) {
- qof_book_merge_match_orphans(mergeData);
- }
-
- check = g_list_copy(mergeData->mergeList);
- while(check != NULL) {
- currentRule = check->data;
- if(currentRule->mergeResult == MERGE_INVALID) {
- mergeData->abort = TRUE;
- return(NULL);
- }
- check = g_list_next(check);
- }
- g_list_free(check);
- return mergeData;
-}
-
-void
-qof_book_merge_abort (qof_book_mergeData *mergeData)
-{
- qof_book_mergeRule *currentRule;
-
- g_return_if_fail(mergeData != NULL);
- while(mergeData->mergeList != NULL) {
- currentRule = mergeData->mergeList->data;
- g_slist_free(currentRule->linkedEntList);
- g_slist_free(currentRule->mergeParam);
- g_free(mergeData->mergeList->data);
- if(currentRule) {
- g_slist_free(currentRule->linkedEntList);
- g_slist_free(currentRule->mergeParam);
- g_free(currentRule);
- }
- mergeData->mergeList = g_list_next(mergeData->mergeList);
- }
- g_list_free(mergeData->mergeList);
- g_slist_free(mergeData->mergeObjectParams);
- g_slist_free(mergeData->targetList);
- if(mergeData->orphan_list != NULL) { g_slist_free(mergeData->orphan_list); }
- g_hash_table_destroy(mergeData->target_table);
- g_free(mergeData);
-}
-
-/* The QOF_TYPE_DATE output format from
-qof_book_merge_param_as_string has been changed to QSF_XSD_TIME,
-a UTC formatted timestring: 2005-01-01T10:55:23Z
-If you change QOF_UTC_DATE_FORMAT, change
-backend/file/qsf-xml.c : qsf_entity_foreach to
-reformat to QSF_XSD_TIME or the QSF XML will
-FAIL the schema validation and QSF exports will become invalid.
-
-The QOF_TYPE_BOOLEAN is lowercase for the same reason.
-*/
-char*
-qof_book_merge_param_as_string(QofParam *qtparam, QofEntity *qtEnt)
-{
- gchar *param_string, param_date[QOF_DATE_STRING_LENGTH];
- char param_sa[GUID_ENCODING_LENGTH + 1];
- QofType paramType;
- const GUID *param_guid;
- time_t param_t;
- gnc_numeric param_numeric, (*numeric_getter) (QofEntity*, QofParam*);
- Timespec param_ts, (*date_getter) (QofEntity*, QofParam*);
- double param_double, (*double_getter) (QofEntity*, QofParam*);
- gboolean param_boolean, (*boolean_getter) (QofEntity*, QofParam*);
- gint32 param_i32, (*int32_getter) (QofEntity*, QofParam*);
- gint64 param_i64, (*int64_getter) (QofEntity*, QofParam*);
- char param_char, (*char_getter) (QofEntity*, QofParam*);
-
- param_string = NULL;
- paramType = qtparam->param_type;
- if(safe_strcmp(paramType, QOF_TYPE_STRING) == 0) {
- param_string = g_strdup(qtparam->param_getfcn(qtEnt,qtparam));
- if(param_string == NULL) { param_string = ""; }
- return param_string;
- }
- if(safe_strcmp(paramType, QOF_TYPE_DATE) == 0) {
- date_getter = (Timespec (*)(QofEntity*, QofParam*))qtparam->param_getfcn;
- param_ts = date_getter(qtEnt, qtparam);
- param_t = timespecToTime_t(param_ts);
- strftime(param_date, QOF_DATE_STRING_LENGTH, QOF_UTC_DATE_FORMAT, gmtime(¶m_t));
- param_string = g_strdup(param_date);
- return param_string;
- }
- if((safe_strcmp(paramType, QOF_TYPE_NUMERIC) == 0) ||
- (safe_strcmp(paramType, QOF_TYPE_DEBCRED) == 0)) {
- numeric_getter = (gnc_numeric (*)(QofEntity*, QofParam*)) qtparam->param_getfcn;
- param_numeric = numeric_getter(qtEnt,qtparam);
- param_string = g_strdup(gnc_numeric_to_string(param_numeric));
- return param_string;
- }
- if(safe_strcmp(paramType, QOF_TYPE_GUID) == 0) {
- param_guid = qtparam->param_getfcn(qtEnt,qtparam);
- guid_to_string_buff(param_guid, param_sa);
- param_string = g_strdup(param_sa);
- return param_string;
- }
- if(safe_strcmp(paramType, QOF_TYPE_INT32) == 0) {
- int32_getter = (gint32 (*)(QofEntity*, QofParam*)) qtparam->param_getfcn;
- param_i32 = int32_getter(qtEnt, qtparam);
- param_string = g_strdup_printf("%d", param_i32);
- return param_string;
- }
- if(safe_strcmp(paramType, QOF_TYPE_INT64) == 0) {
- int64_getter = (gint64 (*)(QofEntity*, QofParam*)) qtparam->param_getfcn;
- param_i64 = int64_getter(qtEnt, qtparam);
- param_string = g_strdup_printf("%" G_GINT64_FORMAT, param_i64);
- return param_string;
- }
- if(safe_strcmp(paramType, QOF_TYPE_DOUBLE) == 0) {
- double_getter = (double (*)(QofEntity*, QofParam*)) qtparam->param_getfcn;
- param_double = double_getter(qtEnt, qtparam);
- param_string = g_strdup_printf("%f", param_double);
- return param_string;
- }
- if(safe_strcmp(paramType, QOF_TYPE_BOOLEAN) == 0){
- boolean_getter = (gboolean (*)(QofEntity*, QofParam*)) qtparam->param_getfcn;
- param_boolean = boolean_getter(qtEnt, qtparam);
- /* Boolean values need to be lowercase for QSF validation. */
- if(param_boolean == TRUE) { param_string = g_strdup("true"); }
- else { param_string = g_strdup("false"); }
- return param_string;
- }
- /* "kvp" contains repeating values, cannot be a single string for the frame. */
- if(safe_strcmp(paramType, QOF_TYPE_KVP) == 0) { return param_string; }
- if(safe_strcmp(paramType, QOF_TYPE_CHAR) == 0) {
- char_getter = (char (*)(QofEntity*, QofParam*)) qtparam->param_getfcn;
- param_char = char_getter(qtEnt, qtparam);
- param_string = g_strdup_printf("%c", param_char);
- return param_string;
- }
- return NULL;
-}
-
-qof_book_mergeData*
-qof_book_mergeUpdateResult(qof_book_mergeData *mergeData,
- qof_book_mergeResult tag)
-{
- qof_book_mergeRule *resolved;
-
- g_return_val_if_fail((mergeData != NULL), NULL);
- g_return_val_if_fail((tag > 0), NULL);
- g_return_val_if_fail((tag != MERGE_REPORT), NULL);
- resolved = mergeData->currentRule;
- g_return_val_if_fail((resolved != NULL), NULL);
- if((resolved->mergeAbsolute == TRUE)&&(tag == MERGE_DUPLICATE))
- {
- tag = MERGE_ABSOLUTE;
- }
- if((resolved->mergeAbsolute == TRUE)&&(tag == MERGE_NEW))
- {
- tag = MERGE_UPDATE;
- }
- if((resolved->mergeAbsolute == FALSE)&& (tag == MERGE_ABSOLUTE))
- {
- tag = MERGE_DUPLICATE;
- }
- if((resolved->mergeResult == MERGE_NEW)&&(tag == MERGE_UPDATE))
- {
- tag = MERGE_NEW;
- }
- if(resolved->updated == FALSE) { resolved->mergeResult = tag; }
- resolved->updated = TRUE;
- if(tag >= MERGE_INVALID) {
- mergeData->abort = TRUE;
- mergeData->currentRule = resolved;
- return NULL;
- }
- mergeData->currentRule = resolved;
- return mergeData;
-}
-
-int
-qof_book_mergeCommit( qof_book_mergeData *mergeData )
-{
- qof_book_mergeRule *currentRule;
- GList *check;
-
- g_return_val_if_fail(mergeData != NULL, -1);
- g_return_val_if_fail(mergeData->mergeList != NULL, -1);
- g_return_val_if_fail(mergeData->targetBook != NULL, -1);
- if(mergeData->abort == TRUE) return -1;
- check = g_list_copy(mergeData->mergeList);
- g_return_val_if_fail(check != NULL, -1);
- while(check != NULL) {
- currentRule = check->data;
- if(currentRule->mergeResult == MERGE_INVALID) {
- qof_book_merge_abort(mergeData);
- return(-2);
- }
- if(currentRule->mergeResult == MERGE_REPORT) {
- g_list_free(check);
- return 1;
- }
- check = g_list_next(check);
- }
- qof_book_mergeCommitForeach( qof_book_mergeCommitRuleLoop, MERGE_NEW, mergeData);
- qof_book_mergeCommitForeach( qof_book_mergeCommitRuleLoop, MERGE_UPDATE, mergeData);
- /* Placeholder for QofObject merge_helper_cb - all objects and all parameters set */
- while(mergeData->mergeList != NULL) {
- currentRule = mergeData->mergeList->data;
- g_slist_free(currentRule->mergeParam);
- g_slist_free(currentRule->linkedEntList);
- mergeData->mergeList = g_list_next(mergeData->mergeList);
- }
- g_list_free(mergeData->mergeList);
- g_slist_free(mergeData->mergeObjectParams);
- g_slist_free(mergeData->targetList);
- if(mergeData->orphan_list != NULL) { g_slist_free(mergeData->orphan_list); }
- g_hash_table_destroy(mergeData->target_table);
- g_free(mergeData);
- return 0;
-}
-
-void
-qof_book_mergeRuleForeach( qof_book_mergeData *mergeData,
- qof_book_mergeRuleForeachCB cb,
- qof_book_mergeResult mergeResult )
-{
- struct qof_book_mergeRuleIterate iter;
- qof_book_mergeRule *currentRule;
- GList *matching_rules;
-
- g_return_if_fail(cb != NULL);
- g_return_if_fail(mergeData != NULL);
- currentRule = mergeData->currentRule;
- g_return_if_fail(mergeResult > 0);
- g_return_if_fail(mergeResult != MERGE_INVALID);
- g_return_if_fail(mergeData->abort == FALSE);
- iter.fcn = cb;
- iter.data = mergeData;
- matching_rules = NULL;
- iter.ruleList = g_list_copy(mergeData->mergeList);
- while(iter.ruleList!=NULL) {
- currentRule = iter.ruleList->data;
- if(currentRule->mergeResult == mergeResult) {
- matching_rules = g_list_prepend(matching_rules, currentRule);
- }
- iter.ruleList = g_list_next(iter.ruleList);
- }
- iter.remainder = g_list_length(matching_rules);
- g_list_foreach (matching_rules, qof_book_mergeRuleCB, &iter);
- g_list_free(matching_rules);
-}
-
-/* End of file. */
-/* ==================================================================== */
Deleted: gnucash/trunk/src/engine/qof_book_merge.h
===================================================================
--- gnucash/trunk/src/engine/qof_book_merge.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qof_book_merge.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,461 +0,0 @@
-/*********************************************************************
- * qof_book_merge.h -- api for QofBook merge with collision handling *
- * Copyright (C) 2004 Neil Williams <linux at codehelp.co.uk> *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
- ********************************************************************/
-
-#ifndef QOFBOOKMERGE_H
-#define QOFBOOKMERGE_H
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-#define QOF_MOD_MERGE "qof-merge"
-
-/** @addtogroup BookMerge
-
-<b>Collision handling principles.</b>\n
-\n
- -# Always check for a ::GUID first and compare. qof_book_merge only accepts valid ::QofBook
- data and therefore ALL objects in the import book will include valid GUID's.
- -# If the original import data did not contain a GUID (e.g. an external non-GnuCash source)
- the GUID values will have been created during the import and will not match any existing
- GUID's in the target book so objects that do not have a GUID match cannot be assumed to
- be ::MERGE_NEW - parameter values must be checked.
- -# If import contains data from closed books, store the data from the closed
- books in the current book as active. i.e. re-open the books.
-
-- If a GUID match exists, set qof_book_mergeRule::mergeAbsolute to \a TRUE.
- -# If ALL parameters in the import object match the target object with the same \a GUID,
- set ::qof_book_mergeResult to \a MERGE_ABSOLUTE.
- -# If any parameters differ, set ::MERGE_UPDATE.
-- If the import object \a GUID does not match an existing object,
-mergeAbsolute is unchanged from the default \a FALSE
-The parameter values of the object are compared to other objects of the same
-type in the target book.
- -# If the same data exists in the target book with a different GUID, the object
- is tagged as DUPLICATE.
- -# If the data has changed, the object is tagged as REPORT.
- -# If the data does not match, the object is tagged as NEW
-
-More information is at http://code.neil.williamsleesmill.me.uk/
-
-Each foreach function uses g_return_if_fail checks to protect the target book. If
-any essential data is missing, the loop returns without changing the target book.
-Note that this will not set or return an error value. However, g_return is only
-used for critical errors that arise from programming errors, not for invalid import data
-which should be cleaned up before creating the import QofBook.
-
-Only ::qof_book_mergeUpdateResult and ::qof_book_mergeCommit return
-any error values to the calling process. ::qof_book_mergeInit returns a
-pointer to the ::qof_book_mergeData struct - the calling process needs to
-make sure this is non-NULL to know that the Init has been successful.
-
- @{
-*/
-/** @file qof_book_merge.h
- @brief API for merging two \c QofBook structures with collision handling
- @author Copyright (c) 2004-2005 Neil Williams <linux at codehelp.co.uk>
-*/
-
-#include <glib.h>
-#include "gnc-engine-util.h"
-#include "qofbook.h"
-#include "qofclass.h"
-#include "qofobject.h"
-#include "qofinstance.h"
-#include "gnc-trace.h"
-
-/** \brief Results of collisions and user resolution.
-
-All rules are initialised as ::MERGE_UNDEF.
-Once the comparison is complete, each object within the import will be
-updated.
-
-::MERGE_ABSOLUTE, ::MERGE_NEW, ::MERGE_DUPLICATE and ::MERGE_UPDATE can be reported
-to the user along with all ::MERGE_REPORT objects for confirmation.
-It may be useful later to allow \a MERGE_ABSOLUTE, \a MERGE_NEW, \a MERGE_DUPLICATE and
-\a MERGE_UPDATE to not be reported, if the user sets a preferences option
-for each result. (Always accept new items: Y/N default NO, ignores all
-MERGE_NEW if set to Y etc.) This option would not require any changes
-to qof_book_merge.
-
-\a MERGE_NEW, \a MERGE_DUPLICATE and \a MERGE_UPDATE are only actioned after
-conflicts are resolved by the user using a dialog and all \a MERGE_REPORT objects are
-re-assigned to one of MERGE_NEW, MERGE_DUPLICATE or MERGE_UPDATE. There is no automatic
-merge, even if no entities are tagged as MERGE_REPORT, the calling process must still
-check for REPORT items using ::qof_book_mergeRuleForeach and call ::qof_book_mergeCommit.
-
-\a MERGE_INVALID data should be rare and allows for user-abort - the imported file/source
- may be corrupted and the prescence of invalid data should raise concerns that
- the rest of the data may be corrupted, damaged or otherwise altered. If any entity is
- tagged as MERGE_INVALID, the merge operation will abort and leave the target book
- completely unchanged.
-
-\a MERGE_ABSOLUTE is only used for a complete match. The import object contains
-the same data in the same parameters with no omissions or amendments. If any data is missing,
-amended or added, the data is labelled \a MERGE_UPDATE.
-
- Every piece of data has a corresponding result. Only when the count of items labelled
- \a MERGE_REPORT is equal to zero are \a MERGE_NEW and \a MERGE_UPDATE
- items added to the existing book.\n \a MERGE_DUPLICATE items are silently ignored.
- Aborting the dialog/process (by the user or in a program crash) at any point before the
- final commit leaves the existing book completely untouched.
-*/
-typedef enum {
- MERGE_UNDEF, /**< default value before comparison is made. */
- MERGE_ABSOLUTE, /**< GUID exact match, no new data - \b ignore */
- MERGE_NEW, /**< import object does \b not exist in the target book - \b add */
- MERGE_REPORT, /**< import object needs user intervention - \b report */
- MERGE_DUPLICATE, /**< import object with different GUID exactly matches existing GUID - \b ignore */
- MERGE_UPDATE, /**< import object matches an existing entity but includes new or
- modified parameter data - \b update */
- MERGE_INVALID /**< import object didn't match registered object or parameter
- types or user decided to abort - \b abort */
-}qof_book_mergeResult;
-
-/** \brief One rule per entity, built into a single GList for the entire merge
-
-All rules are stored in the GList qof_book_mergeData::mergeList.
-
-If the ::GUID matches it's the always same semantic object,
-regardless of whether other data fields are changed.
-\n
-The boolean value mergeAbsolute defaults to \c FALSE
-
-NOTE 1: if mergeAbsolute == \c TRUE, ::qof_book_mergeResult will still be set to
-::MERGE_UPDATE if parameters within this entity have been modified.
-
-NOTE 2: ::qof_book_merge_param_as_string returns \b string representations of the parameter
-data that is causing a collision. These values must \b NOT be used to set the target
-parameter - the function is provided for display purposes only, to make it simple to
-explain the collision to the user using MERGE_REPORT and the dialog.
-
-The GHashTable targetTable in qof_book_mergeRule will probably replace the GSList of the
-same name in mergeData.
-
-*/
-
-typedef struct
-{
- /* internal counters and reference variables */
- gboolean mergeAbsolute; /**< Only set if the GUID of the import matches the target */
- double difference; /**< used to find best match in a book where no GUID matches */
- gboolean updated; /**< prevent the mergeResult from being overwritten. */
- /* rule objects set from or by external calls */
- QofIdType mergeType; /**< type of comparison required for check for collision */
- const char* mergeLabel; /**< Descriptive label for the object type, useful for the
- user intervention dialog. */
- GSList *mergeParam; /**< list of usable parameters for the object type */
- GSList *linkedEntList; /**< list of complex data types included in this object.
-
- linkedEntList contains an ::QofEntity reference to any parameter that is not
- one of the core QOF_TYPE data types. This entity must be already registered with QOF
- and the results of the comparison for the linked entity will modulate the mergeResult
- of this object. e.g. if an invoice is the same value but for a different customer,
- the invoice will be set to MERGE_REPORT and the customer as MERGE_NEW.
- */
- qof_book_mergeResult mergeResult; /**< result of comparison with main ::QofBook */
- QofEntity *importEnt; /**< pointer to the current entity in the import book. */
- QofEntity *targetEnt; /**< pointer to the corresponding entity in the target book, if any. */
-}qof_book_mergeRule;
-
-
-/** \brief mergeData contains the essential context data for any merge.
-
-Used to dictate what to merge, how to merge it, where to get the new data and
-where to put the amended data.
-
-Combines lists of \a ::QofParam, \a ::QofEntity and \a ::qof_book_mergeRule into one struct that
-can be easily passed between callbacks. Also holds the pointers to the import and target ::QofBook
-structures.
-
-- targetList and mergeObjectParams change each time a new object type is set for compare.
-- mergeList is the complete list of rules for all objects in the import book.
-
-*/
-typedef struct
-{
- GSList *mergeObjectParams; /**< GSList of ::QofParam details for each parameter in the current object. */
- GList *mergeList; /**< GList of all ::qof_book_mergeRule rules for the merge operation. */
- GSList *targetList; /**< GSList of ::QofEntity * for each object of this type in the target book */
- QofBook *mergeBook; /**< pointer to the import book for this merge operation. */
- QofBook *targetBook; /**< pointer to the target book for this merge operation. */
- gboolean abort; /**< set to TRUE if MERGE_INVALID is set. */
- qof_book_mergeRule *currentRule; /**< placeholder for the rule currently being tested or applied. */
- GSList *orphan_list; /**< List of QofEntity's that need to be rematched.
-
- When one QofEntity has a lower difference to the targetEnt than the previous best_match,
- the new match takes precedence. This list holds those orphaned entities that are not a good
- enough match so that these can be rematched later. The ranking is handled using
- the private qof_entity_rating struct and the GHashTable ::qof_book_mergeData::target_table.
- */
- GHashTable *target_table; /**< The GHashTable to hold the qof_entity_rating values. */
-
-}qof_book_mergeData;
-
-
-/* ======================================================================== */
-/** @name qof_book_merge API
- @{
-*/
-/** \brief Initialise the qof_book_merge process
-
- First function of the qof_book_merge API. Every merge must begin with Init.
-
- Requires the book to import (::QofBook *) and the book to receive the import, the target book
- (::QofBook *). Returns a pointer to ::qof_book_mergeData which must be checked for a
- NULL before continuing. \n
-Process:
-
- -# Invoke the callback ::qof_book_mergeForeachType on every registered object class definition.
- -# Callback obtains the registered parameter list for each object type. This provides run time
- access to all registered objects and all object parameters without any changes to
- qof_book_merge - no registered object or parameter is omitted from any merge operation.
- -# Use ::qof_object_foreach to invoke the callback ::qof_book_mergeForeach, one object at a time
- on every instance stored in mergeBook. This is the first point where real data from the import
- book is accessed.
- -# qof_book_mergeForeach obtains the ::GUID for the object from the import book and runs the first
- check on the original book, checking for any exact GUID match. With the full parameter list,
- the rules for this object can be created. If there is a GUID match, the data in each parameter
- of the import object is compared with the same semantic object in the original book. If there is
- no GUID in the import object or no GUID match with the original book, the original book is
- searched to find a parameter match - checking for a ::MERGE_DUPLICATE result.
- -# ::qof_book_mergeCompare sets the ::qof_book_mergeResult of the comparison.
- -# Inserts the completed rule into qof_book_mergeData::mergeList GSList.
-
-\return NULL in case of error, otherwise a ::qof_book_mergeData* metadata context.
-
-*/
-qof_book_mergeData*
-qof_book_mergeInit( QofBook *importBook, QofBook *targetBook);
-
-
-/** \brief Definition of the dialog control callback routine
-
-All ::MERGE_REPORT rules must be offered for user intervention using this template.\n
-Commit will fail if any rules are still tagged as \a MERGE_REPORT.
-
-Calling processes are free to also offer MERGE_NEW, MERGE_UPDATE, MERGE_DUPLICATE and
-MERGE_ABSOLUTE for user intervention. Attempting to query MERGE_INVALID rules
-will cause an error.
-
-For an example, consider test_rule_loop, declared as:
-
-<tt>void test_rule_loop(qof_book_mergeData *mergeData, qof_book_mergeRule *rule, guint remainder);\n
-void test_rule_loop(qof_book_mergeData *mergeData, qof_book_mergeRule *rule, guint remainder) \n
-{\n
- g_return_if_fail(rule != NULL);\n
- g_return_if_fail(mergeData != NULL);
- printf("Rule Result %s", rule->mergeType);\n
- qof_book_mergeUpdateResult(mergeData, rule, MERGE_UPDATE);\n
-}</tt>
-
-The dialog is free to call ::qof_book_mergeUpdateResult in the loop or at the end
-as long as the link between the rule and the result is maintained, e.g. by using a
-GHashTable.
-\n
-The parameters are:
- - data : pointer to the ::qof_book_mergeData metadata context returned by Init.
- - rule : pointer to the ::qof_book_mergeRule that generated the collision report
- - remainder : guint value returned from g_slist_length for the number of other
- rules remaining with the same result. This might be useful for a progress dialog, it might not.
- When updating MERGE_REPORT, remainder must equal zero before calling
- ::qof_book_mergeCommit or the import will abort.
-\n
-
-If the dialog sets \b any rule result to ::MERGE_INVALID, the import will abort when
-::qof_book_mergeCommit is called. It is the responsibility of the calling function to
-handle the error code from ::qof_book_mergeCommit, close the dialog and return.
-The merge routines in these files will already have halted the merge operation and
-freed any memory allocated to merge structures before returning the error code.
-There is no need for the dialog process to report back to qof_book_merge in this situation.
-*/
-typedef void (* qof_book_mergeRuleForeachCB)( qof_book_mergeData*, qof_book_mergeRule*, guint);
-
-/** \brief Dialog Control Callback
-
-This function is designed to be used to iterate over all rules tagged with a specific
-::qof_book_mergeResult value.
-
- at param callback external loop of type qof_book_mergeRuleForeachCB
- at param mergeResult ::qof_book_mergeResult value to look up.
- at param mergeData ::qof_book_mergeData merge context.
-
-\b Note : MERGE_NEW causes a new entity to be created in the target book at Commit
-which is then assigned as the targetEnt of that rule. If mergeResult == MERGE_NEW,
-the rules returned by qof_book_mergeRuleForeach will have a NULL set for the targetEnt.
-This is because Commit has not yet been called and no changes can be made to the target
-book. The calling process must handle the NULL targetEnt and NOT call any param_getfcn
-routines for the target entity. The import entity is available for display.
-
-Uses ::qof_book_get_collection with the qof_book_mergeRule::mergeType object type to
-return a collection of ::QofEntity entities from either the qof_book_mergeData::mergeBook or
-qof_book_mergeData::targetBook. Then uses ::qof_collection_lookup_entity to lookup
-the qof_book_mergeRule::importEnt and again the qof_book_mergeRule::targetEnt to
-return the two specific entities.
-
-*/
-void qof_book_mergeRuleForeach( qof_book_mergeData* mergeData,
- qof_book_mergeRuleForeachCB callback ,
- qof_book_mergeResult mergeResult);
-
-/** \brief provides easy string access to parameter data for dialog use
-
-Uses the param_getfcn to retrieve the parameter value as a string, suitable for
-display in dialogs and user intervention output. Within a qof_book_merge context,
-only the parameters used in the merge are available, i.e. parameters where both
-param_getfcn and param_setfcn are not NULL.
-
-Note that the object type description (a full text version of the object name) is
-also available to the dialog as qof_book_mergeRule::mergeLabel.
-
-This allows the dialog to display the description of the object and all parameter data.
-
-*/
-char* qof_book_merge_param_as_string(QofParam *qtparam, QofEntity *qtEnt);
-
-/** \brief called by dialog callback to set the result of user intervention
-
-Set \b any rule result to ::MERGE_INVALID to abort the import when
-::qof_book_mergeCommit is called, without changing the target book.
-
-The calling process should make it absolutely clear that a merge operation
-\b cannot be undone and that a backup copy should always be available
-\b before a merge is initialised.
-
-Recommended method: Only offer three options to the user per rule:
-
--# Allow import data to be merged into target data
- - change MERGE_REPORT to MERGE_UPDATE
--# Allow import data without an exact match to be
- added as new
- - change MERGE_REPORT to MERGE_NEW \b IF mergeAbsolute = FALSE
--# Ignore import data and leave target data unchanged
- - change MERGE_REPORT to MERGE_ABSOLUTE or MERGE_DUPLICATE
-
-Handle the required result changes in code: Check the value of
-qof_book_mergeRule::mergeAbsolute and use these principles:
-
-To ignore entities tagged as:
-- MERGE_REPORT, you must check the value of mergeAbsolute.
- - if mergeAbsolute is TRUE, change MERGE_REPORT to MERGE_ABSOLUTE
- - if mergeAbsolute is FALSE, change MERGE_REPORT to MERGE_DUPLICATE
-- MERGE_NEW, set MERGE_DUPLICATE.
-- MERGE_UPDATE, you must check the value of mergeAbsolute.
- - if mergeAbsolute is TRUE, change MERGE_UPDATE to MERGE_ABSOLUTE
- - if mergeAbsolute is FALSE, change MERGE_UPDATE to MERGE_DUPLICATE
-
-To merge entities that are not pre-set to MERGE_NEW, set MERGE_UPDATE.\n
-Attempting to merge an entity when the pre-set value was MERGE_NEW will
-force a change back to MERGE_NEW because no suitable target exists for the
-merge.
-
-To add entities, check mergeAbsolute is FALSE and set MERGE_NEW.\n
-An entity \b only be added if mergeAbsolute is FALSE. Attempting to
-add an entity when mergeAbsolute is TRUE will always force a MERGE_UPDATE.
-
-It is not possible to update the same rule more than once.
-
--# \b MERGE_NEW is reserved for new objects and is only pre-set if
-all parameters, including GUID, have already failed to match any
-relevant object. ::qof_book_mergeCommit will create new
-entities for all rules tagged as MERGE_NEW.
- - if mergeAbsolute is TRUE and the user wants to import the
- data, requests to set MERGE_NEW will be forced to MERGE_UPDATE
- because an entity with that GUID already exists in the target book.
- - if MERGE_NEW is pre-set, requests to change to MERGE_UPDATE will be
- ignored because a new entity is needed.
--# \b MERGE_UPDATE is reserved for existing objects - ::qof_book_mergeCommit
-will require a matching entity to update and will force a change to back to
-MERGE_NEW if none is known to exist, using the principle above.
--# \b MERGE_INVALID will cause an abort of the merge process.
--# \b MERGE_UNDEF and \b MERGE_REPORT cannot be set - the entity result will be unchanged.
--# \b MERGE_DUPLICATE and \b MERGE_ABSOLUTE are handled identically but are semantically
- different - qof_book_mergeRule::mergeAbsolute is used to dictate which to set:
- - if mergeAbsolute is TRUE but MERGE_DUPLICATE is requested,
- force a change to MERGE_ABSOLUTE.
- - if mergeAbsolute is FALSE but MERGE_ABSOLUTE is requested,
- force a change to MERGE_DUPLICATE.
-
-::qof_book_mergeCommit only commits entities tagged
-with MERGE_NEW and MERGE_UPDATE results.
-\n
-Entities tagged with MERGE_ABSOLUTE and MERGE_DUPLICATE results are ignored.
-
-The calling process must check the return value and call
-::qof_book_merge_abort(mergeData) if non-zero.
-
- at param mergeData the merge context, ::qof_book_mergeData*
- at param tag the result to attempt to set, ::qof_book_mergeResult
-
-\return -1 if supplied parameters are invalid or NULL, 0 on success.
-
-*/
-qof_book_mergeData*
-qof_book_mergeUpdateResult(qof_book_mergeData *mergeData, qof_book_mergeResult tag);
-
-
-/** \brief Commits the import data to the target book
-
- The last function in the API and the final part of any qof_book_merge operation.
-
-qof_book_mergeCommit will abort the \b entire merge operation if any rule is set to
-::MERGE_INVALID. It is the responsibility of the calling
-function to handle the error code from ::qof_book_mergeCommit, close the dialog
-and return. qof_book_mergeCommit will already have halted the merge
-operation and freed any memory allocated to all merge structures before returning the error
-code. There is no way for the dialog process to report back to qof_book_merge in this situation.
-
-qof_book_mergeCommit checks for any entities still tagged as ::MERGE_REPORT and then proceeds
-to import all entities tagged as ::MERGE_UPDATE or ::MERGE_NEW into the target book.
-\n
-<b>This final process cannot be UNDONE!</b>\n
-\n
-
- at param mergeData the merge context, ::qof_book_mergeData*
-
-\return
- - -2 if any rules are tagged as ::MERGE_INVALID
- - mergeData will have been g_free'd).
- - note that this will be before any operations are done on the target
- QofBook.
- - -1 if mergeData is invalid or no merge has been initialised with
- ::qof_book_mergeInit - the calling process must check the value of mergeData
- - +1 if some entities are still tagged as \a MERGE_REPORT - use
- ::qof_book_mergeUpdateRule and try again (mergeData is retained).
- - 0 on success - mergeData will have been freed.
-*/
-int
-qof_book_mergeCommit( qof_book_mergeData *mergeData );
-
-/** \brief Abort the merge and free all memory allocated by the merge
-
-Sometimes, setting ::MERGE_INVALID is insufficient: e.g. if the user aborts the
-merge from outside the functions dealing with the merge ruleset. This function
-causes an immediate abort - the calling process must start again at Init if
-a new merge is required.
-*/
-void
-qof_book_merge_abort(qof_book_mergeData *mergeData);
-
-#endif // QOFBOOKMERGE_H
-/** @} */
-/** @} */
Deleted: gnucash/trunk/src/engine/qofbackend-p.h
===================================================================
--- gnucash/trunk/src/engine/qofbackend-p.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofbackend-p.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,410 +0,0 @@
-/********************************************************************\
- * qofbackend-p.h -- private api for data storage backend *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-/** @addtogroup Object
- @{ */
-/** @addtogroup Object_Private
- Private interfaces, not meant to be used by applications.
- @{ */
-/** @name Backend_Private
- Pseudo-object defining how the engine can interact with different
- back-ends (which may be SQL databases, or network interfaces to
- remote GnuCash servers. File-io is just one type of backend).
-
- The callbacks will be called at the appropriate times during
- a book session to allow the backend to store the data as needed.
-
- @file qofbackend-p.h
- @brief private api for data storage backend
- @author Copyright (c) 2000,2001,2004 Linas Vepstas <linas at linas.org>
- @author Copyright (c) 2005 Neil Williams <linux at codehelp.co.uk>
-@{ */
-
-#ifndef QOF_BACKEND_P_H
-#define QOF_BACKEND_P_H
-
-#include "config.h"
-#include "qof-be-utils.h"
-#include "qofbackend.h"
-#include "qofbook.h"
-#include "qofinstance-p.h"
-#include "qofquery.h"
-#include "qofsession.h"
-
-/**
- * The session_begin() routine gives the backend a second initialization
- * opportunity. It is suggested that the backend check that
- * the URL is syntactically correct, and that it is actually
- * reachable. This is probably(?) a good time to initialize
- * the actual network connection.
- *
- * The 'ignore_lock' argument indicates whether the single-user
- * lock on the backend should be cleared. The typical GUI sequence
- * leading to this is: (1) GUI attempts to open the backend
- * by calling this routine with FALSE==ignore_lock. (2) If backend
- * error'ed BACKEND_LOCK, then GUI asks user what to do. (3) if user
- * answers 'break & enter' then this routine is called again with
- * TRUE==ignore_lock.
- *
- * The 'create_if_nonexistent' argument indicates whether this
- * routine should create a new 'database', if it doesn't already
- * exist. For example, for a file-backend, this would create the
- * file, if it didn't already exist. For an SQL backend, this
- * would create the database (the schema) if it didn't already
- * exist. This flag is used to implement the 'SaveAs' GUI, where
- * the user requests to save data to a new backend.
- *
- * The load() routine should load the minimal set of application data
- * needed for the application to be operable at initial startup.
- * It is assumed that the application will perform a 'run_query()'
- * to obtain any additional data that it needs. For file-based
- * backends, it is acceptable for the backend to return all data
- * at load time; for SQL-based backends, it is acceptable for the
- * backend to return no data.
- *
- * Thus, for example, for GnuCash, the postrges backend returns
- * the account tree, all currencies, and the pricedb, as these
- * are needed at startup. It does not have to return any
- * transactions whatsoever, as these are obtained at a later stage
- * when a user opens a register, resulting in a query being sent to
- * the backend.
- *
- * (Its OK to send over transactions at this point, but one should
- * be careful of the network load; also, its possible that whatever
- * is sent is not what the user wanted anyway, which is why its
- * better to wait for the query).
- *
- * The begin() routine is called when the engine is about to
- * make a change to a data structure. It can provide an advisory
- * lock on data.
- *
- * The commit() routine commits the changes from the engine to the
- * backend data storage.
- *
- * The rollback() routine is used to revert changes in the engine
- * and unlock the backend. For transactions it is invoked in one
- * of two different ways. In one case, the user may hit 'undo' in
- * the GUI, resulting in xaccTransRollback() being called, which in
- * turn calls this routine. In this manner, xaccTransRollback()
- * implements a single-level undo convenience routine for the GUI.
- * The other way in which this routine gets invoked involves
- * conflicting edits by two users to the same transaction. The
- * second user to make an edit will typically fail in
- * trans_commit_edit(), with trans_commit_edit() returning an error
- * code. This causes xaccTransCommitEdit() to call
- * xaccTransRollback() which in turn calls this routine. Thus,
- * this routine gives the backend a chance to clean up failed
- * commits.
- *
- * If the second user tries to modify a transaction that
- * the first user deleted, then the backend should set the error
- * to ERR_BACKEND_MOD_DESTROY from this routine, so that the
- * engine can properly clean up.
- *
- * The compile_query() method compiles a Gnucash query object into
- * a backend-specific data structure and returns the compiled
- * query. For an SQL backend, the contents of the query object
- * need to be turned into a corresponding SQL query statement, and
- * sent to the database for evaluation.
- *
- * The free_query() method frees the data structure returned from
- * compile_query()
- *
- * The run_query() callback takes a compiled query (generated by
- * compile_query) and runs the query in across the backend,
- * inserting the responses into the engine. The database will
- * return a set of splits and transactions, and this callback needs
- * to poke these into the account-group hierarchy held by the query
- * object.
- *
- * For a network-communications backend, essentially the same is
- * done, except that this routine would convert the query to wire
- * protocol, get an answer from the remote server, and push that
- * into the account-group object.
- *
- * Note a peculiar design decision we've used here. The query
- * callback has returned a list of splits; these could be returned
- * directly to the caller. They are not. By poking them into the
- * existing account hierarchy, we are essentially building a local
- * cache of the split data. This will allow the GnuCash client to
- * continue functioning even when disconnected from the server:
- * this is because it will have its local cache of data to work from.
- *
- * The sync() routine synchronizes the engine contents to the backend.
- * This is done by using version numbers (hack alert -- the engine
- * does not currently contain version numbers).
- * If the engine contents are newer than what's in the backend, the
- * data is stored to the backend. If the engine contents are older,
- * then the engine contents are updated.
- *
- * Note that this sync operation is only meant to apply to the
- * current contents of the engine. This routine is not intended
- * to be used to fetch account/transaction data from the backend.
- * (It might pull new splits from the backend, if this is what is
- * needed to update an existing transaction. It might pull new
- * currencies (??))
- *
- * The counter() routine increments the named counter and returns the
- * post-incremented value. Returns -1 if there is a problem.
- *
- * The events_pending() routines should return true if there are
- * external events which need to be processed to bring the
- * engine up to date with the backend.
- *
- * The process_events() routine should process any events indicated
- * by the events_pending() routine. It should return TRUE if
- * the engine was changed while engine events were suspended.
- *
- * The last_err member indicates the last error that occurred.
- * It should probably be implemented as an array (actually,
- * a stack) of all the errors that have occurred.
- *
- * For support of book partitioning, use special "Book" begin_edit()
- * and commit_edit() QOF_ID types.
- *
- * Call the book begin() at the begining of a book partitioning. A
- * 'partitioning' is the splitting off of a chunk of the current
- * book into a second book by means of a query. Every transaction
- * in that query is to be moved ('transfered') to the second book
- * from the existing book. The argument of this routine is a
- * pointer to the second book, where the results of the query
- * should go.
- *
- * Cann the book commit() to complete the book partitioning.
- *
- * After the begin(), there will be a call to run_query(), followed
- * probably by a string of account and transaction calls, and
- * completed by commit(). It should be explicitly understood that
- * the results of that run_query() precisely constitute the set of
- * transactions that are to be moved between the initial and the
- * new book. This specification can be used by a clever backend to
- * avoid excess data movement between the server and the gnucash
- * client, as explained below.
- *
- * There are several possible ways in which a backend may choose to
- * implement the book splitting process. A 'file-type' backend may
- * choose to ignore this call, and the subsequent query, and simply
- * write out the new book to a file when the commit() call is made.
- * By that point, the engine will have performed all of the
- * nitty-gritty of moving transactions from one book to the other.
- *
- * A 'database-type' backend has several interesting choices. One
- * simple choice is to simply perform the run_query() as it
- * normally would, and likewise treat the account and transaction
- * edits as usual. In this scenario, the commit() is more or less
- * a no-op. This implementation has a drawback, however: the
- * run_query() may cause the transfer of a *huge* amount of data
- * between the backend and the engine. For a large dataset, this
- * is quite undesirable. In addition, there are risks associated
- * with the loss of network connectivity during the transfer; thus
- * a partition might terminate half-finished, in some indeterminate
- * state, due to network errors. That might be difficult to
- * recover from: the engine does not take any special transactional
- * safety measures during the transfer.
- *
- * Thus, for a large database, an alternate implementation
- * might be to use the run_query() call as an opportunity to
- * transfer transactions between the two books in the database,
- * and not actually return any new data to the engine. In
- * this scenario, the engine will attempt to transfer those
- * transactions that it does know about. It does not, however,
- * need to know about all the other transactions that also would
- * be transfered over. In this way, a backend could perform
- * a mass transfer of transactions between books without having
- * to actually move much (or any) data to the engine.
- *
- *
- * To support configuration options from the frontend, the backend
- * can be passed a GHashTable - according to the allowed options
- * for that backend, using load_config(). Configuration can be
- * updated at any point - it is up to the frontend to load the
- * data in time for whatever the backend needs to do. e.g. an
- * option to save a new book in a compressed format need not be
- * loaded until the backend is about to save. If the configuration
- * is updated by the user, the frontend should call load_config
- * again to update the backend.
- */
-
-struct QofBackendProvider_s
-{
- /** Some arbitrary name given for this particular backend provider */
- const char * provider_name;
-
- /** The access method that this provider provides, for example,
- * http:// or postgres:// or rpc://, but without the :// at the end
- */
- const char * access_method;
-
- /** \brief Partial QofBook handler
-
- TRUE if the backend handles external references
- to entities outside this book and can save a QofBook that
- does not contain any specific QOF objects.
- */
- gboolean partial_book_supported;
-
- /** Return a new, initialized backend backend. */
- QofBackend * (*backend_new) (void);
-
-/** \brief Distinguish two providers with same access method.
-
- More than 1 backend can be registered under the same access_method,
- so each one is passed the path to the data (e.g. a file) and
- should return TRUE only:
--# if the backend recognises the type as one that it can load and write or
--# if the path contains no data but can be used (e.g. a new session).
-
- \note If the backend can cope with more than one type, the backend
- should not try to store or cache the sub-type for this data.
- It is sufficient only to return TRUE if any ONE of the supported
- types match the incoming data. The backend should not assume that
- returning TRUE will mean that the data will naturally follow.
- */
- gboolean (*check_data_type) (const char*);
-
- /** Free this structure, unregister this backend handler. */
- void (*provider_free) (QofBackendProvider *);
-};
-
-struct QofBackend_s
-{
- void (*session_begin) (QofBackend *be,
- QofSession *session,
- const char *book_id,
- gboolean ignore_lock,
- gboolean create_if_nonexistent);
- void (*session_end) (QofBackend *);
- void (*destroy_backend) (QofBackend *);
-
- void (*load) (QofBackend *, QofBook *);
-
- void (*begin) (QofBackend *, QofInstance *);
- void (*commit) (QofBackend *, QofInstance *);
- void (*rollback) (QofBackend *, QofInstance *);
-
- gpointer (*compile_query) (QofBackend *, QofQuery *);
- void (*free_query) (QofBackend *, gpointer);
- void (*run_query) (QofBackend *, gpointer);
-
- void (*sync) (QofBackend *, QofBook *);
- void (*load_config) (QofBackend *, KvpFrame *);
- KvpFrame* (*get_config) (QofBackend *);
- gint64 (*counter) (QofBackend *, const char *counter_name);
-
- gboolean (*events_pending) (QofBackend *);
- gboolean (*process_events) (QofBackend *);
-
- QofBePercentageFunc percentage;
-
- QofBackendProvider *provider;
-
- /** Document Me !!! what is this supposed to do ?? */
- gboolean (*save_may_clobber_data) (QofBackend *);
-
- QofBackendError last_err;
- char * error_msg;
-
- KvpFrame* backend_configuration;
- gint config_count;
- /** Each backend resolves a fully-qualified file path.
- * This holds the filepath and communicates it to the frontends.
- */
- char * fullpath;
-
-#ifdef GNUCASH_MAJOR_VERSION
- /** XXX price_lookup should be removed during the redesign
- * of the SQL backend... prices can now be queried using
- * the generic query mechanism.
- *
- * Note the correct signature for this call is
- * void (*price_lookup) (QofBackend *, GNCPriceLookup *);
- * we use gpointer to avoid an unwanted include file dependency.
- */
- void (*price_lookup) (QofBackend *, gpointer);
-
- /** XXX Export should really _NOT_ be here, but is left here for now.
- * I'm not sure where this should be going to. It should be
- * removed ASAP. This is a temporary hack-around until period-closing
- * is fully implemented.
- */
- void (*export) (QofBackend *, QofBook *);
-#endif
-
-};
-
-/** Let the sytem know about a new provider of backends. This function
- * is typically called by the provider library at library load time.
- * This function allows the backend library to tell the QOF infrastructure
- * that it can handle URL's of a certain type. Note that a single
- * backend library may register more than one provider, if it is
- * capable of handling more than one URL access method.
- */
-void qof_backend_register_provider (QofBackendProvider *);
-
-/** The qof_backend_set_error() routine pushes an error code onto the error
- * stack. (FIXME: the stack is 1 deep in current implementation).
- */
-void qof_backend_set_error (QofBackend *be, QofBackendError err);
-
-/** The qof_backend_get_error() routine pops an error code off the error stack.
- */
-QofBackendError qof_backend_get_error (QofBackend *be);
-
-/** The qof_backend_set_message() assigns a string to the backend error message.
- */
-void qof_backend_set_message(QofBackend *be, const char *format, ...);
-
-/** The qof_backend_get_message() pops the error message string from
- * the Backend. This string should be freed with g_free().
- */
-char * qof_backend_get_message(QofBackend *be);
-
-void qof_backend_init(QofBackend *be);
-
-/** Allow backends to see if the book is open
-
- at return 'y' if book is open, otherwise 'n'.
-*/
-gchar qof_book_get_open_marker(QofBook *book);
-
-/** get the book version
-
-used for tracking multiuser updates in backends.
-
- at return -1 if no book exists, 0 if the book is
-new, otherwise the book version number.
-*/
-gint32 qof_book_get_version (QofBook *book);
-
-/** get the book tag number
-
-used for kvp management in sql backends.
-*/
-guint32 qof_book_get_idata (QofBook *book);
-
-void qof_book_set_version (QofBook *book, gint32 version);
-
-void qof_book_set_idata(QofBook *book, guint32 idata);
-
-/* @} */
-/* @} */
-/* @} */
-#endif /* QOF_BACKEND_P_H */
Deleted: gnucash/trunk/src/engine/qofbackend.c
===================================================================
--- gnucash/trunk/src/engine/qofbackend.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofbackend.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,427 +0,0 @@
-/********************************************************************\
- * qofbackend.c -- utility routines for dealing with the data backend *
- * Copyright (C) 2000 Linas Vepstas <linas at linas.org> *
- * Copyright (C) 2004-5 Neil Williams <linux at codehelp.co.uk> *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-#define _GNU_SOURCE
-#include "config.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <regex.h>
-#include <glib.h>
-#include <gmodule.h>
-#include <dlfcn.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include "qofbackend-p.h"
-
-static QofLogModule log_module = QOF_MOD_BACKEND;
-
-#define QOF_CONFIG_DESC "desc"
-#define QOF_CONFIG_TIP "tip"
-
-/********************************************************************\
- * error handling *
-\********************************************************************/
-
-void
-qof_backend_set_error (QofBackend *be, QofBackendError err)
-{
- if (!be) return;
-
- /* use stack-push semantics. Only the earliest error counts */
- if (ERR_BACKEND_NO_ERR != be->last_err) return;
- be->last_err = err;
-}
-
-QofBackendError
-qof_backend_get_error (QofBackend *be)
-{
- QofBackendError err;
- if (!be) return ERR_BACKEND_NO_BACKEND;
-
- /* use 'stack-pop' semantics */
- err = be->last_err;
- be->last_err = ERR_BACKEND_NO_ERR;
- return err;
-}
-
-void
-qof_backend_set_message (QofBackend *be, const char *format, ...)
-{
- va_list args;
- char * buffer;
-
- if (!be) return;
-
- /* If there's already something here, free it */
- if (be->error_msg) g_free(be->error_msg);
-
- if (!format) {
- be->error_msg = NULL;
- return;
- }
-
- va_start(args, format);
- buffer = (char *)g_strdup_vprintf(format, args);
- va_end(args);
-
- be->error_msg = buffer;
-}
-
-/* This should always return a valid char * */
-char *
-qof_backend_get_message (QofBackend *be)
-{
- char * msg;
-
- if (!be) return g_strdup("ERR_BACKEND_NO_BACKEND");
- if (!be->error_msg) return NULL;
-
- /*
- * Just return the contents of the error_msg and then set it to
- * NULL. This is necessary, because the Backends don't seem to
- * have a destroy_backend function to take care if freeing stuff
- * up. The calling function should free the copy.
- * Also, this is consistent with the qof_backend_get_error() popping.
- */
-
- msg = be->error_msg;
- be->error_msg = NULL;
- return msg;
-}
-
-/***********************************************************************/
-/* Get a clean backend */
-void
-qof_backend_init(QofBackend *be)
-{
- be->session_begin = NULL;
- be->session_end = NULL;
- be->destroy_backend = NULL;
-
- be->load = NULL;
-
- be->begin = NULL;
- be->commit = NULL;
- be->rollback = NULL;
-
- be->compile_query = NULL;
- be->free_query = NULL;
- be->run_query = NULL;
-
- be->sync = NULL;
- be->load_config = NULL;
-
- be->events_pending = NULL;
- be->process_events = NULL;
-
- be->last_err = ERR_BACKEND_NO_ERR;
- if (be->error_msg) g_free (be->error_msg);
- be->error_msg = NULL;
- be->percentage = NULL;
- be->backend_configuration = kvp_frame_new();
-
-#ifdef GNUCASH_MAJOR_VERSION
- /* XXX remove these */
- be->fullpath = NULL;
- be->price_lookup = NULL;
- be->export = NULL;
-#endif
-}
-
-void
-qof_backend_run_begin(QofBackend *be, QofInstance *inst)
-{
- if(!be || !inst) { return; }
- if(!be->begin) { return; }
- (be->begin) (be, inst);
-}
-
-gboolean
-qof_backend_begin_exists(QofBackend *be)
-{
- if(be->begin) { return TRUE; }
- else { return FALSE; }
-}
-
-void
-qof_backend_run_commit(QofBackend *be, QofInstance *inst)
-{
- if(!be || !inst) { return; }
- if(!be->commit) { return; }
- (be->commit) (be, inst);
-}
-
-/* =========== Backend Configuration ================ */
-
-void qof_backend_prepare_frame(QofBackend *be)
-{
- g_return_if_fail(be);
- if(!kvp_frame_is_empty(be->backend_configuration)) {
- kvp_frame_delete(be->backend_configuration);
- be->backend_configuration = kvp_frame_new();
- }
- be->config_count = 0;
-}
-
-void qof_backend_prepare_option(QofBackend *be, QofBackendOption *option)
-{
- KvpValue *value;
- gchar *temp;
- gint count;
-
- g_return_if_fail(be || option);
- count = be->config_count;
- count++;
- value = NULL;
- ENTER (" %d", count);
- switch (option->type)
- {
- case KVP_TYPE_GINT64 : {
- value = kvp_value_new_gint64(*(gint64*)option->value);
- break;
- }
- case KVP_TYPE_DOUBLE : {
- value = kvp_value_new_double(*(double*)option->value);
- break;
- }
- case KVP_TYPE_NUMERIC : {
- value = kvp_value_new_numeric(*(gnc_numeric*)option->value);
- break;
- }
- case KVP_TYPE_STRING : {
- value = kvp_value_new_string((const char*)option->value);
- break;
- }
- case KVP_TYPE_GUID : { break; } /* unsupported */
- case KVP_TYPE_TIMESPEC : {
- value = kvp_value_new_timespec(*(Timespec*)option->value);
- break;
- }
- case KVP_TYPE_BINARY : { break; } /* unsupported */
- case KVP_TYPE_GLIST : { break; } /* unsupported */
- case KVP_TYPE_FRAME : { break; } /* unsupported */
- }
- if(value) {
- temp = g_strdup_printf("/%s", option->option_name);
- kvp_frame_set_value(be->backend_configuration, temp, value);
- PINFO (" setting value at %s", temp);
- g_free(temp);
- temp = g_strdup_printf("/%s/%s", QOF_CONFIG_DESC, option->option_name);
- PINFO (" setting description %s at %s", option->description, temp);
- kvp_frame_set_string(be->backend_configuration, temp, option->description);
- PINFO (" check= %s", kvp_frame_get_string(be->backend_configuration, temp));
- g_free(temp);
- temp = g_strdup_printf("/%s/%s", QOF_CONFIG_TIP, option->option_name);
- PINFO (" setting tooltip %s at %s", option->tooltip, temp);
- kvp_frame_set_string(be->backend_configuration, temp, option->tooltip);
- PINFO (" check= %s", kvp_frame_get_string(be->backend_configuration, temp));
- g_free(temp);
- /* only increment the counter if successful */
- be->config_count = count;
- }
- LEAVE (" ");
-}
-
-KvpFrame* qof_backend_complete_frame(QofBackend *be)
-{
- g_return_val_if_fail(be, NULL);
- be->config_count = 0;
- return be->backend_configuration;
-}
-
-struct config_iterate {
- QofBackendOptionCB fcn;
- gpointer data;
- gint count;
- KvpFrame *recursive;
-};
-
-static void
-config_foreach_cb (const char *key, KvpValue *value, gpointer data)
-{
- QofBackendOption option;
- gint64 int64;
- double db;
- gnc_numeric num;
- Timespec ts;
- gchar *parent;
- struct config_iterate *helper;
-
- g_return_if_fail(key || value || data);
- helper = (struct config_iterate*)data;
- if(!helper->recursive) { PERR (" no parent frame"); return; }
- // skip the presets.
- if(0 == safe_strcmp(key, QOF_CONFIG_DESC)) { return; }
- if(0 == safe_strcmp(key, QOF_CONFIG_TIP)) { return; }
- ENTER (" key=%s", key);
- option.option_name = key;
- option.type = kvp_value_get_type(value);
- if(!option.type) { return; }
- switch (option.type)
- {
- case KVP_TYPE_GINT64 : {
- int64 = kvp_value_get_gint64(value);
- option.value = (gpointer)&int64;
- break;
- }
- case KVP_TYPE_DOUBLE : {
- db = kvp_value_get_double(value);
- option.value = (gpointer)&db;
- break;
- }
- case KVP_TYPE_NUMERIC : {
- num = kvp_value_get_numeric(value);
- option.value = (gpointer)#
- break;
- }
- case KVP_TYPE_STRING : {
- option.value = (gpointer)kvp_value_get_string(value);
- break;
- }
- case KVP_TYPE_GUID : { break; } /* unsupported */
- case KVP_TYPE_TIMESPEC : {
- ts = kvp_value_get_timespec(value);
- option.value = (gpointer)&ts;
- break;
- }
- case KVP_TYPE_BINARY : { break; } /* unsupported */
- case KVP_TYPE_GLIST : { break; } /* unsupported */
- case KVP_TYPE_FRAME : { break; } /* unsupported */
- }
- parent = g_strdup_printf("/%s/%s", QOF_CONFIG_DESC, key);
- option.description = kvp_frame_get_string(helper->recursive, parent);
- g_free(parent);
- parent = g_strdup_printf("/%s/%s", QOF_CONFIG_TIP, key);
- option.tooltip = kvp_frame_get_string(helper->recursive, parent);
- helper->count++;
- helper->fcn (&option, helper->data);
- LEAVE (" desc=%s tip=%s", option.description, option.tooltip);
-}
-
-void qof_backend_option_foreach(KvpFrame *config, QofBackendOptionCB cb, gpointer data)
-{
- struct config_iterate helper;
-
- if(!config || !cb) { return; }
- ENTER (" ");
- helper.fcn = cb;
- helper.count = 1;
- helper.data = data;
- helper.recursive = config;
- kvp_frame_for_each_slot(config, config_foreach_cb, &helper);
- LEAVE (" ");
-}
-
-void
-qof_backend_load_config(QofBackend *be, KvpFrame *config)
-{
- if(!be || !config) { return; }
- if(!be->load_config) { return; }
- (be->load_config) (be, config);
-}
-
-KvpFrame*
-qof_backend_get_config(QofBackend *be)
-{
- if(!be) { return NULL; }
- if(!be->get_config) { return NULL; }
- return (be->get_config) (be);
-}
-
-gboolean
-qof_backend_commit_exists(QofBackend *be)
-{
- if(!be) { return FALSE; }
- if(be->commit) { return TRUE; }
- else { return FALSE; }
-}
-
-gboolean
-qof_begin_edit(QofInstance *inst)
-{
- QofBackend * be;
-
- if (!inst) { return FALSE; }
- (inst->editlevel)++;
- if (1 < inst->editlevel) { return FALSE; }
- if (0 >= inst->editlevel) { inst->editlevel = 1; }
- be = qof_book_get_backend (inst->book);
- if (be && qof_backend_begin_exists(be)) {
- qof_backend_run_begin(be, inst);
- } else { inst->dirty = TRUE; }
- return TRUE;
-}
-
-gboolean qof_commit_edit(QofInstance *inst)
-{
- QofBackend * be;
-
- if (!inst) { return FALSE; }
- (inst->editlevel)--;
- if (0 < inst->editlevel) { return FALSE; }
- if ((-1 == inst->editlevel) && inst->dirty)
- {
- be = qof_book_get_backend ((inst)->book);
- if (be && qof_backend_begin_exists(be)) {
- qof_backend_run_begin(be, inst);
- }
- inst->editlevel = 0;
- }
- if (0 > inst->editlevel) { inst->editlevel = 0; }
- return TRUE;
-}
-
-gboolean
-qof_load_backend_library (const char *directory,
- const char* filename, const char* init_fcn)
-{
- struct stat sbuf;
- gchar *fullpath;
- typedef void (* backend_init) (void);
- GModule *backend;
- backend_init gmod_init;
- gpointer g;
-
- g_return_val_if_fail(g_module_supported(), FALSE);
- fullpath = g_module_build_path(directory, filename);
- PINFO (" fullpath=%s", fullpath);
- g_return_val_if_fail((stat(fullpath, &sbuf) == 0), FALSE);
- backend = g_module_open(fullpath, G_MODULE_BIND_LAZY);
- if(!backend) {
- g_message ("%s: %s\n", PACKAGE, g_module_error ());
- return FALSE;
- }
- g = &gmod_init;
- if (!g_module_symbol (backend, init_fcn, g))
- {
- g_message ("%s: %s\n", PACKAGE, g_module_error ());
- return FALSE;
- }
- g_module_make_resident(backend);
- gmod_init();
- return TRUE;
-}
-
-/************************* END OF FILE ********************************/
Deleted: gnucash/trunk/src/engine/qofbackend.h
===================================================================
--- gnucash/trunk/src/engine/qofbackend.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofbackend.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,265 +0,0 @@
-/********************************************************************\
- * qofbackend.h: api for data storage backend *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-/** @addtogroup Backend
-
- The QOF Backend is a pseudo-object providing an interface between the
- engine and a persistant data store (e.g. a server, a database, or
- a file). Backends are not meant to be used directly by an
- application; instead the Session should be used to make a
- connection with some particular backend.
- There are no backend functions that are 'public' to
- users of the engine. The backend can, however, report errors to
- the GUI & other front-end users. This file defines these errors.
-
- Backends are used to save and restore Entities in a Book.
- @{
-*/
-/** @file qofbackend.h
- @brief API for data storage Backend
- @author Copyright (C) 2000-2001 Linas Vepstas <linas at linas.org>
- @author Copyright 2004-2005 Neil Williams <linux at codehelp.co.uk>
-*/
-
-#ifndef QOF_BACKEND_H
-#define QOF_BACKEND_H
-
-#include "qofinstance.h"
-
-#define QOF_MOD_BACKEND "qof-backend"
-
-/** \brief The errors that can be reported to the GUI & other front-end users
- * \warning (GnuCash) If you modify QofBackendError, please update
- * src/engine/gw-engine-spec.scm
-*/
-typedef enum {
- ERR_BACKEND_NO_ERR = 0,
- ERR_BACKEND_NO_HANDLER, /**< no backend handler found for this access method (ENOSYS) */
- ERR_BACKEND_NO_BACKEND, /**< Backend * pointer was unexpectedly null */
- ERR_BACKEND_BAD_URL, /**< Can't parse url */
- ERR_BACKEND_NO_SUCH_DB, /**< the named database doesn't exist */
- ERR_BACKEND_CANT_CONNECT, /**< bad dbname/login/passwd or network failure */
- ERR_BACKEND_CONN_LOST, /**< Lost connection to server */
- ERR_BACKEND_LOCKED, /**< in use by another user (ETXTBSY) */
- ERR_BACKEND_READONLY, /**< cannot write to file/directory */
- ERR_BACKEND_TOO_NEW, /**< file/db version newer than what we can read */
- ERR_BACKEND_DATA_CORRUPT, /**< data in db is corrupt */
- ERR_BACKEND_SERVER_ERR, /**< error in response from server */
- ERR_BACKEND_ALLOC, /**< internal memory allocation failure */
- ERR_BACKEND_PERM, /**< user login successful, but no permissions
- to access the desired object */
- ERR_BACKEND_MODIFIED, /**< commit of object update failed because
- another user has modified the object */
- ERR_BACKEND_MOD_DESTROY, /**< commit of object update failed because
- another user has deleted the object */
- ERR_BACKEND_MISC, /**< undetermined error */
-
- /* QSF add-ons */
- ERR_QSF_INVALID_OBJ, /**< The QSF object failed to validate against the QSF object schema */
- ERR_QSF_INVALID_MAP, /**< The QSF map failed to validate against the QSF map schema */
- ERR_QSF_BAD_OBJ_GUID, /**< The QSF object contains one or more invalid GUIDs. */
- ERR_QSF_BAD_QOF_VERSION, /**< QSF map or object doesn't match the current QOF_OBJECT_VERSION. */
- ERR_QSF_BAD_MAP, /**< The selected map validates but is unusable.
-
- This is usually because not all the required parameters for the defined objects
- have calculations described in the map.
- */
- ERR_QSF_NO_MAP, /**< The QSF object file was loaded without a map
-
- The QSF Object file requires a map but it was not provided.
- */
- ERR_QSF_WRONG_MAP, /**< The selected map validates but is for different objects.
-
- The list of objects defined in this map does not include all the objects described in
- the current QSF object file.
- */
- ERR_QSF_MAP_NOT_OBJ, /**< Selected file is a QSF map and cannot be opened as a QSF object */
- ERR_QSF_OVERFLOW, /**< EOVERFLOW - generated by strtol or strtoll.
-
- When converting XML strings into numbers, an overflow has been detected. The XML file
- contains invalid data in a field that is meant to hold a signed long integer or signed long long
- integer.
- */
- ERR_QSF_OPEN_NOT_MERGE, /** QSF files cannot be opened alone. The data must be merged.
-
- This error is more of a warning that can be ignored by any routine
- that uses qof_book_merge on the new session.
- */
- /* fileio errors */
- ERR_FILEIO_FILE_BAD_READ = 1000, /**< read failed or file prematurely truncated */
- ERR_FILEIO_FILE_EMPTY, /**< file exists, is readable, but is empty */
- ERR_FILEIO_FILE_LOCKERR, /**< mangled locks (unspecified error) */
- ERR_FILEIO_FILE_NOT_FOUND, /**< not found / no such file */
- ERR_FILEIO_FILE_TOO_OLD, /**< file version so old we can't read it */
- ERR_FILEIO_UNKNOWN_FILE_TYPE, /**< didn't recognize the file type */
- ERR_FILEIO_PARSE_ERROR, /**< couldn't parse the data in the file */
- ERR_FILEIO_BACKUP_ERROR, /**< couldn't make a backup of the file */
- ERR_FILEIO_WRITE_ERROR, /**< couldn't write to the file */
-
- /* network errors */
- ERR_NETIO_SHORT_READ = 2000, /**< not enough bytes received */
- ERR_NETIO_WRONG_CONTENT_TYPE, /**< wrong kind of server, wrong data served */
- ERR_NETIO_NOT_GNCXML, /**< whatever it is, we can't parse it. */
-
- /* database errors */
- ERR_SQL_MISSING_DATA = 3000, /**< database doesn't contain expected data */
- ERR_SQL_DB_TOO_OLD, /**< database is old and needs upgrading */
- ERR_SQL_DB_BUSY, /**< database is busy, cannot upgrade version */
-
- /* RPC errors */
- ERR_RPC_HOST_UNK = 4000, /**< Host unknown */
- ERR_RPC_CANT_BIND, /**< can't bind to address */
- ERR_RPC_CANT_ACCEPT, /**< can't accept connection */
- ERR_RPC_NO_CONNECTION, /**< no connection to server */
- ERR_RPC_BAD_VERSION, /**< RPC Version Mismatch */
- ERR_RPC_FAILED, /**< Operation failed */
- ERR_RPC_NOT_ADDED, /**< object not added */
-} QofBackendError;
-
-/**
- * A structure that declares backend services that can be gotten.
- * The Provider specifies a URL access method, and specifies the
- * function to create a backend that can handle that URL access
- * function.
- */
-typedef struct QofBackendProvider_s QofBackendProvider;
-
-/** \brief Pseudo-object providing an interface between the
- * engine and a persistant data store (e.g. a server, a database,
- * or a file).
- *
- * There are no backend functions that are 'public' to users of the
- * engine. The backend can, however, report errors to the GUI & other
- * front-end users.
- */
-typedef struct QofBackend_s QofBackend;
-
-/** \brief DOCUMENT ME! */
-typedef void (*QofBePercentageFunc) (const char *message, double percent);
-
-/** @name Allow access to the begin routine for this backend.
-
-QOF_BEGIN_EDIT and QOF_COMMIT_EDIT_PART1 and part2 rely on
-calling QofBackend *be->begin and be->commit. This means the
-QofBackend struct becomes part of the public API.
-These function replaces those calls to allow the macros to be
-used when QOF is built as a library. */
-//@{
-
-void qof_backend_run_begin(QofBackend *be, QofInstance *inst);
-
-gboolean qof_backend_begin_exists(QofBackend *be);
-
-void qof_backend_run_commit(QofBackend *be, QofInstance *inst);
-
-gboolean qof_backend_commit_exists(QofBackend *be);
-//@}
-
-/** @name Backend Configuration using KVP
-
-The backend uses qof_backend_get_config to pass back a KvpFrame of QofBackendOption
-that includes the \b translated strings that serve as description and
-tooltip for that option. i.e. backends need to run gettext in the init function.
-
-qof_backend_prepare_frame, qof_backend_prepare_option and qof_backend_complete_frame
-are intended to be used by the backend itself to create the options.
-
-qof_backend_get_config, qof_backend_option_foreach and qof_backend_load_config
-are intended for either the backend or the frontend to retrieve the option data
-from the frame or set new data.
-
-@{
-*/
-
-/** A single Backend Configuration Option. */
-typedef struct QofBackendOption_s {
- KvpValueType type; /**< Only GINT64, DOUBLE, NUMERIC, STRING and TIMESPEC supported. */
- const char *option_name; /**< non-translated, key. */
- const char *description; /**< translatable description. */
- const char *tooltip; /**< translatable tooltip */
- gpointer value; /**< The value of the option. */
-}QofBackendOption;
-
-/** Initialise the backend_configuration */
-void qof_backend_prepare_frame(QofBackend *be);
-
-/** Add an option to the backend_configuration. Repeat for more. */
-void qof_backend_prepare_option(QofBackend *be, QofBackendOption *option);
-
-/** Complete the backend_configuration and return the frame. */
-KvpFrame* qof_backend_complete_frame(QofBackend *be);
-
-/** Backend configuration option foreach callback prototype. */
-typedef void (*QofBackendOptionCB)(QofBackendOption*, gpointer data);
-
-/** Iterate over the frame and process each option. */
-void qof_backend_option_foreach(KvpFrame *config, QofBackendOptionCB cb, gpointer data);
-
-/** \brief Load configuration options specific to this backend.
-
- at param be The backend to configure.
- at param config A KvpFrame of QofBackendOptions that this backend
-will recognise. Each backend needs to document their own config
-types and acceptable values.
-
-*/
-void qof_backend_load_config (QofBackend *be, KvpFrame *config);
-
-/** \brief Get the available configuration options
-
-To retrieve the options from the returned KvpFrame, the caller
-needs to parse the XML file that documents the option names and
-data types. The XML file itself is part of the backend and is
-installed in a directory determined by the backend. Therefore,
-loading a new backend requires two paths: the path to the .la file
-and the path to the xml. Both paths are available by including a
-generated header file, e.g. gncla-dir.h defines GNC_LIB_DIR for
-the location of the .la file and GNC_XML_DIR for the xml.
-
- at param be The QofBackend to be configured.
-
- at return A new KvpFrame containing the available options or
-NULL on failure.
-
-*/
-KvpFrame* qof_backend_get_config(QofBackend *be);
-//@}
-
-/** \brief Load a QOF-compatible backend shared library.
-
-\param directory Can be NULL if filename is a complete path.
-\param filename Name of the .la file that describes the
- shared library. This provides platform independence,
- courtesy of libtool.
-\param init_fcn The QofBackendProvider init function.
-
-\return FALSE in case or error, otherwise TRUE.
-*/
-gboolean
-qof_load_backend_library (const char *directory,
- const char* filename, const char* init_fcn);
-
-/** \brief Retrieve the backend used by this book */
-QofBackend* qof_book_get_backend (QofBook *book);
-
-void qof_book_set_backend (QofBook *book, QofBackend *);
-
-#endif /* QOF_BACKEND_H */
-/** @} */
Deleted: gnucash/trunk/src/engine/qofbook-p.h
===================================================================
--- gnucash/trunk/src/engine/qofbook-p.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofbook-p.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,114 +0,0 @@
-/********************************************************************\
- * qof-book-p.h -- private functions for QOF books. *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-/** @addtogroup Object
- @{ */
-/** @addtogroup Object_Private
- Private interfaces, not meant to be used by applications.
- @{ */
-/** @name Book_Private
- @{ */
-/*
- * HISTORY:
- * Created 2001 by Rob Browning
- * Copyright (c) 2001 Rob Browning
- * Copyright (c) 2001,2003 Linas Vepstas <linas at linas.org>
- */
-
-#ifndef QOF_BOOK_P_H
-#define QOF_BOOK_P_H
-
-#include "kvp_frame.h"
-#include "qofbackend.h"
-#include "qofbook.h"
-#include "qofid.h"
-#include "qofid-p.h"
-#include "qofinstance-p.h"
-
-/** Book structure */
-struct _QofBook
-{
- QofInstance inst; /**< Unique guid for this book. */
-
- /** The entity table associates the GUIDs of all the objects
- * belonging to this book, with their pointers to the respective
- * objects. This allows a lookup of objects based on thier guid.
- */
- GHashTable * hash_of_collections;
-
- /** In order to store arbitrary data, for extensibility, add a table
- * that will be used to hold arbitrary pointers.
- */
- GHashTable *data_tables;
-
- /** Hash table of destroy callbacks for the data table. */
- GHashTable *data_table_finalizers;
-
- /** state flag: 'y' means 'open for editing',
- * 'n' means 'book is closed'
- * xxxxx shouldn't this be replaced by the instance editlevel ???
- */
- char book_open;
-
- /** a flag denoting whether the book is closing down, used to
- * help the QOF objects shut down cleanly without maintaining
- * internal consistency.
- * XXX shouldn't this be replaced by instance->do_free ???
- */
- gboolean shutting_down;
-
- /** version number, used for tracking multiuser updates */
- gint32 version;
-
- /** To be technically correct, backends belong to sessions and
- * not books. So the pointer below "really shouldn't be here",
- * except that it provides a nice convenience, avoiding a lookup
- * from the session. Better solutions welcome ... */
- QofBackend *backend;
-
- /* -------------------------------------------------------------- */
- /** Backend private expansion data */
- guint32 idata; /**< used by the sql backend for kvp management */
-};
-
-/**
- * These qof_book_set_*() routines are used by backends to
- * initialize the pointers in the book structure to
- * something that contains actual data. These routines
- * should not be used otherwise. (Its somewhat questionable
- * if the backends should even be doing this much, but for
- * backwards compatibility, we leave these here.)
- */
-void qof_book_set_schedxactions( QofBook *book, GList *newList );
-
-void qof_book_set_backend (QofBook *book, QofBackend *be);
-
-/** Register books with the engine */
-gboolean qof_book_register (void);
-
-/** @deprecated */
-#define qof_book_set_guid(book,guid) \
- qof_entity_set_guid(QOF_ENTITY(book), guid)
-
-/* @} */
-/* @} */
-/* @} */
-#endif /* QOF_BOOK_P_H */
Deleted: gnucash/trunk/src/engine/qofbook.c
===================================================================
--- gnucash/trunk/src/engine/qofbook.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofbook.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,387 +0,0 @@
-/********************************************************************\
- * qofbook.c -- dataset access (set of accounting books) *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
-\********************************************************************/
-
-/*
- * FILE:
- * qofbook.c
- *
- * FUNCTION:
- * Encapsulate all the information about a gnucash dataset.
- * See src/doc/books.txt for design overview.
- *
- * HISTORY:
- * Created by Linas Vepstas December 1998
- * Copyright (c) 1998-2001,2003 Linas Vepstas <linas at linas.org>
- * Copyright (c) 2000 Dave Peticolas
- */
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include "gnc-event.h"
-#include "gnc-event-p.h"
-#include "gnc-trace.h"
-#include "qofbackend-p.h"
-#include "qofbook.h"
-#include "qofbook-p.h"
-#include "qofclass.h"
-#include "qofid-p.h"
-#include "qofobject-p.h"
-#include "gnc-engine-util.h"
-
-#include "guid.h"
-
-static QofLogModule log_module = QOF_MOD_ENGINE;
-
-/* ====================================================================== */
-/* constructor / destructor */
-
-static void coll_destroy(gpointer col)
-{
- qof_collection_destroy((QofCollection *) col);
-}
-
-static void
-qof_book_init (QofBook *book)
-{
- if (!book) return;
-
- book->hash_of_collections = g_hash_table_new_full(
- g_str_hash, g_str_equal,
- (GDestroyNotify)gnc_string_cache_remove, /* key_destroy_func */
- coll_destroy); /* value_destroy_func */
-
- qof_instance_init (&book->inst, QOF_ID_BOOK, book);
-
- book->data_tables = g_hash_table_new (g_str_hash, g_str_equal);
- book->data_table_finalizers = g_hash_table_new (g_str_hash, g_str_equal);
-
- book->book_open = 'y';
- book->version = 0;
- book->idata = 0;
-}
-
-QofBook *
-qof_book_new (void)
-{
- QofBook *book;
-
- ENTER (" ");
- book = g_new0(QofBook, 1);
- qof_book_init(book);
- qof_object_book_begin (book);
-
- gnc_engine_gen_event (&book->inst.entity, GNC_EVENT_CREATE);
- LEAVE ("book=%p", book);
- return book;
-}
-
-static void
-book_final (gpointer key, gpointer value, gpointer booq)
-{
- QofBookFinalCB cb = value;
- QofBook *book = booq;
-
- gpointer user_data = g_hash_table_lookup (book->data_tables, key);
- (*cb) (book, key, user_data);
-}
-
-void
-qof_book_destroy (QofBook *book)
-{
- if (!book) return;
- ENTER ("book=%p", book);
-
- book->shutting_down = TRUE;
- gnc_engine_force_event (&book->inst.entity, GNC_EVENT_DESTROY);
-
- /* Call the list of finalizers, let them do their thing.
- * Do this before tearing into the rest of the book.
- */
- g_hash_table_foreach (book->data_table_finalizers, book_final, book);
-
- qof_object_book_end (book);
-
- g_hash_table_destroy (book->data_table_finalizers);
- book->data_table_finalizers = NULL;
- g_hash_table_destroy (book->data_tables);
- book->data_tables = NULL;
-
- qof_instance_release (&book->inst);
-
- g_hash_table_destroy (book->hash_of_collections);
- book->hash_of_collections = NULL;
-
- g_free (book);
- LEAVE ("book=%p", book);
-}
-
-/* ====================================================================== */
-/* XXX this should probably be calling is_equal callbacks on gncObject */
-
-gboolean
-qof_book_equal (QofBook *book_1, QofBook *book_2)
-{
- if (book_1 == book_2) return TRUE;
- if (!book_1 || !book_2) return FALSE;
- return TRUE;
-}
-
-/* ====================================================================== */
-
-gboolean
-qof_book_not_saved(QofBook *book)
-{
- if (!book) return FALSE;
-
- return(book->inst.dirty || qof_object_is_dirty (book));
-}
-
-void
-qof_book_mark_saved(QofBook *book)
-{
- if (!book) return;
-
- book->inst.dirty = FALSE;
- qof_object_mark_clean (book);
-}
-
-/* ====================================================================== */
-/* getters */
-
-QofBackend *
-qof_book_get_backend (QofBook *book)
-{
- if (!book) return NULL;
- return book->backend;
-}
-
-gboolean
-qof_book_shutting_down (QofBook *book)
-{
- if (!book) return FALSE;
- return book->shutting_down;
-}
-
-/* ====================================================================== */
-/* setters */
-
-void
-qof_book_set_backend (QofBook *book, QofBackend *be)
-{
- if (!book) return;
- ENTER ("book=%p be=%p", book, be);
- book->backend = be;
- LEAVE (" ");
-}
-
-void qof_book_kvp_changed (QofBook *book)
-{
- if (!book) return;
- book->inst.dirty = TRUE;
-}
-
-/* ====================================================================== */
-
-/* Store arbitrary pointers in the QofBook for data storage extensibility */
-/* XXX if data is NULL, we should remove the key from the hash table!
- */
-void
-qof_book_set_data (QofBook *book, const char *key, gpointer data)
-{
- if (!book || !key) return;
- g_hash_table_insert (book->data_tables, (gpointer)key, data);
-}
-
-void
-qof_book_set_data_fin (QofBook *book, const char *key, gpointer data, QofBookFinalCB cb)
-{
- if (!book || !key) return;
- g_hash_table_insert (book->data_tables, (gpointer)key, data);
-
- if (!cb) return;
- g_hash_table_insert (book->data_table_finalizers, (gpointer)key, cb);
-}
-
-gpointer
-qof_book_get_data (QofBook *book, const char *key)
-{
- if (!book || !key) return NULL;
- return g_hash_table_lookup (book->data_tables, (gpointer)key);
-}
-
-/* ====================================================================== */
-
-QofCollection *
-qof_book_get_collection (QofBook *book, QofIdType entity_type)
-{
- QofCollection *col;
-
- if (!book || !entity_type) return NULL;
-
- col = g_hash_table_lookup (book->hash_of_collections, entity_type);
- if (!col) {
- col = qof_collection_new (entity_type);
- g_hash_table_insert(
- book->hash_of_collections,
- gnc_string_cache_insert((gpointer) entity_type), col);
- }
- return col;
-}
-
-struct _iterate {
- QofCollectionForeachCB fn;
- gpointer data;
-};
-
-static void
-foreach_cb (gpointer key, gpointer item, gpointer arg)
-{
- struct _iterate *iter = arg;
- QofCollection *col = item;
-
- iter->fn (col, iter->data);
-}
-
-void
-qof_book_foreach_collection (QofBook *book,
- QofCollectionForeachCB cb, gpointer user_data)
-{
- struct _iterate iter;
-
- g_return_if_fail (book);
- g_return_if_fail (cb);
-
- iter.fn = cb;
- iter.data = user_data;
-
- g_hash_table_foreach (book->hash_of_collections, foreach_cb, &iter);
-}
-
-/* ====================================================================== */
-
-void qof_book_mark_closed (QofBook *book)
-{
- if(!book) { return; }
- book->book_open = 'n';
-}
-
-gchar qof_book_get_open_marker(QofBook *book)
-{
- if(!book) { return 'n'; }
- return book->book_open;
-}
-
-gint32 qof_book_get_version (QofBook *book)
-{
- if(!book) { return -1; }
- return book->version;
-}
-
-guint32 qof_book_get_idata (QofBook *book)
-{
- if(!book) { return 0; }
- return book->idata;
-}
-
-void qof_book_set_version (QofBook *book, gint32 version)
-{
- if(!book && version < 0) { return; }
- book->version = version;
-}
-
-void qof_book_set_idata(QofBook *book, guint32 idata)
-{
- if(!book && idata < 0) { return; }
- book->idata = idata;
-}
-
-gint64
-qof_book_get_counter (QofBook *book, const char *counter_name)
-{
- QofBackend *be;
- KvpFrame *kvp;
- KvpValue *value;
- gint64 counter;
-
- if (!book) {
- PWARN ("No book!!!");
- return -1;
- }
-
- if (!counter_name || *counter_name == '\0') {
- PWARN ("Invalid counter name.");
- return -1;
- }
-
- /* If we've got a backend with a counter method, call it */
- be = book->backend;
- if (be && be->counter)
- return ((be->counter)(be, counter_name));
-
- /* If not, then use the KVP in the book */
- kvp = qof_book_get_slots (book);
-
- if (!kvp) {
- PWARN ("Book has no KVP_Frame");
- return -1;
- }
-
- value = kvp_frame_get_slot_path (kvp, "counters", counter_name, NULL);
- if (value) {
- /* found it */
- counter = kvp_value_get_gint64 (value);
- } else {
- /* New counter */
- counter = 0;
- }
-
- /* Counter is now valid; increment it */
- counter++;
-
- /* Save off the new counter */
- value = kvp_value_new_gint64 (counter);
- kvp_frame_set_slot_path (kvp, value, "counters", counter_name, NULL);
- kvp_value_delete (value);
-
- /* and return the value */
- return counter;
-}
-
-/* QofObject function implementation and registration */
-gboolean qof_book_register (void)
-{
- static QofParam params[] = {
- { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_entity_get_guid, NULL },
- { QOF_PARAM_KVP, QOF_TYPE_KVP, (QofAccessFunc)qof_instance_get_slots, NULL },
- { NULL },
- };
-
- qof_class_register (QOF_ID_BOOK, NULL, params);
-
- return TRUE;
-}
-
-/* ========================== END OF FILE =============================== */
Deleted: gnucash/trunk/src/engine/qofbook.h
===================================================================
--- gnucash/trunk/src/engine/qofbook.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofbook.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,178 +0,0 @@
-/********************************************************************\
- * qofbook.h -- Encapsulate all the information about a dataset. *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-/** @addtogroup Object
- @{ */
-/** @addtogroup Book
- A QOF Book is a dataset. It provides a single handle
- through which all the various collections of entities
- can be found. In particular, given only the type of
- the entity, the collection can be found.
-
- Books also provide the 'natural' place to working with
- a storage backend, as a book can encapsulate everything
- held in storage.
- @{ */
-/** @file qofbook.h
- * @brief Encapsulate all the information about a dataset.
- *
- * @author Copyright (c) 1998, 1999, 2001, 2003 Linas Vepstas <linas at linas.org>
- * @author Copyright (c) 2000 Dave Peticolas
- */
-
-#ifndef QOF_BOOK_H
-#define QOF_BOOK_H
-
-#include <glib.h>
-#include "qofid.h"
-#include "kvp_frame.h"
-
-/** @brief Encapsulates all the information about a dataset
- * manipulated by GnuCash. This is the top-most structure
- * used for anchoring data.
- */
-
-/** Lookup an entity by guid, returning pointer to the entity */
-#define QOF_BOOK_LOOKUP_ENTITY(book,guid,e_type,c_type) ({ \
- QofEntity *val = NULL; \
- if (guid && book) { \
- QofCollection *col; \
- col = qof_book_get_collection (book, e_type); \
- val = qof_collection_lookup_entity (col, guid); \
- } \
- (c_type *) val; \
-})
-
-/** \brief QofBook reference */
-typedef struct _QofBook QofBook;
-
-/** GList of QofBook */
-typedef GList QofBookList;
-
-typedef void (*QofBookFinalCB) (QofBook *, gpointer key, gpointer user_data);
-
-/** Register the book object with the QOF object system. */
-gboolean qof_book_register (void);
-
-/** Allocate, initialise and return a new QofBook. Books contain references
- * to all of the top-level object containers. */
-QofBook * qof_book_new (void);
-
-/** End any editing sessions associated with book, and free all memory
- associated with it. */
-void qof_book_destroy (QofBook *book);
-
-/** Close a book to editing.
-
-It is up to the application to check this flag,
-and once marked closed, books cannnot be marked as open.
-*/
-void qof_book_mark_closed (QofBook *book);
-
-/** \return The table of entities of the given type.
- *
- * When an object's constructor calls qof_instance_init(), a
- * reference to the object is stored in the book. The book stores
- * all the references to initialized instances, sorted by type. This
- * function returns a collection of the references for the specified
- * type.
- *
- * If the collection doesn't yet exist for the indicated type,
- * it is created. Thus, this routine is gaurenteed to return
- * a non-NULL value. (Unless the system malloc failed (out of
- * memory) in which case what happens??).
- */
-QofCollection * qof_book_get_collection (QofBook *, QofIdType);
-
-/** Invoke the indicated callback on each collection in the book. */
-typedef void (*QofCollectionForeachCB) (QofCollection *, gpointer user_data);
-void qof_book_foreach_collection (QofBook *, QofCollectionForeachCB, gpointer);
-
-/** \return The kvp data for the book.
- * Note that the book KVP data is persistant, and is stored/retrieved
- * from the file/database. Thus, the book KVP is the correct place to
- * store data that needs to be persistant accross sessions (or shared
- * between multiple users). To store application runtime data, use
- * qof_book_set_data() instead.
- */
-#define qof_book_get_slots(book) qof_instance_get_slots(QOF_INSTANCE(book))
-
-/** The qof_book_set_data() allows arbitrary pointers to structs
- * to be stored in QofBook. This is the "prefered" method for
- * extending QofBook to hold new data types. This is also
- * the ideal location to store other arbitrary runtime data
- * that the application may need.
- *
- * The book data differs from the book KVP in that the contents
- * of the book KVP are persistant (are saved and restored to file
- * or database), whereas the data pointers exist only at runtime.
- */
-void qof_book_set_data (QofBook *book, const char *key, gpointer data);
-
-/** Same as qof_book_set_data(), except that the callback will be called
- * when the book is destroyed. The argument to the callback will be
- * the book followed by the data pointer.
- */
-void qof_book_set_data_fin (QofBook *book, const char *key, gpointer data,
- QofBookFinalCB);
-
-/** Retrieves arbitrary pointers to structs stored by qof_book_set_data. */
-gpointer qof_book_get_data (QofBook *book, const char *key);
-
-/** Is the book shutting down? */
-gboolean qof_book_shutting_down (QofBook *book);
-
-/** qof_book_not_saved() will return TRUE if any
- * data in the book hasn't been saved to long-term storage.
- * (Actually, that's not quite true. The book doesn't know
- * anything about saving. Its just that whenever data is modified,
- * the 'dirty' flag is set. This routine returns the value of the
- * 'dirty' flag. Its up to the backend to periodically reset this
- * flag, when it actually does save the data.)
- */
-gboolean qof_book_not_saved (QofBook *book);
-
-/** The qof_book_mark_saved() routine marks the book as having been
- * saved (to a file, to a database). Used by backends to mark the
- * notsaved flag as FALSE just after loading. Also used by the
- * main window code when the used has said to abandon any changes.
- */
-void qof_book_mark_saved(QofBook *book);
-
-/** Call this function when you change the book kvp, to make sure the book
- * is marked 'dirty'. */
-void qof_book_kvp_changed (QofBook *book);
-
-/** The qof_book_equal() method returns TRUE if books are equal.
- * XXX this routine is broken, and does not currently compare data.
- */
-gboolean qof_book_equal (QofBook *book_1, QofBook *book_2);
-
-/** This will 'get and increment' the named counter for this book.
- * The return value is -1 on error or the incremented counter.
- */
-gint64 qof_book_get_counter (QofBook *book, const char *counter_name);
-
-/** deprecated */
-#define qof_book_get_guid(X) qof_entity_get_guid (QOF_ENTITY(X))
-
-#endif /* QOF_BOOK_H */
-/** @} */
-/** @} */
Deleted: gnucash/trunk/src/engine/qofchoice.c
===================================================================
--- gnucash/trunk/src/engine/qofchoice.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofchoice.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,109 +0,0 @@
-/***************************************************************************
- * qofchoice.c
- *
- * Thu Jul 7 12:24:30 2005
- * Copyright 2005 Neil Williams
- * linux at codehelp.co.uk
- ****************************************************************************/
-/*
- * 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 Library General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <glib.h>
-#include "qofchoice.h"
-
-static GHashTable *qof_choice_table = NULL;
-
-/* To initialise, call qof_choice_add_class in
-qof_object_register for the choice object. */
-static gboolean qof_choice_is_initialized(void)
-{
- if(!qof_choice_table)
- {
- qof_choice_table = g_hash_table_new(g_str_hash, g_str_equal);
- }
- if(!qof_choice_table) { return FALSE; }
- return TRUE;
-}
-
-gboolean qof_object_is_choice(QofIdType type)
-{
- gpointer value, check;
-
- value = NULL;
- check = NULL;
- g_return_val_if_fail(qof_choice_is_initialized(), FALSE);
- g_return_val_if_fail(type != NULL, FALSE);
- value = g_hash_table_lookup(qof_choice_table, type);
- if((GHashTable*)value) { return TRUE; }
- g_message("DEBUG: QOF_TYPE_CHOICE setup failed for %s\n", type);
- return FALSE;
-}
-
-gboolean
-qof_choice_create(char* type)
-{
- GHashTable *param_table;
-
- g_return_val_if_fail(type != NULL, FALSE);
- g_return_val_if_fail(qof_choice_is_initialized() == TRUE, FALSE);
- param_table = g_hash_table_new(g_str_hash, g_str_equal);
- g_hash_table_insert(qof_choice_table, type, param_table);
- return TRUE;
-}
-
-gboolean qof_choice_add_class(char* select, char* option, char* param_name)
-{
- GHashTable *param_table;
- GList *option_list;
-
- option_list = NULL;
- param_table = NULL;
- g_return_val_if_fail(select != NULL, FALSE);
- g_return_val_if_fail(qof_object_is_choice(select), FALSE);
- param_table = (GHashTable*)g_hash_table_lookup(qof_choice_table, select);
- g_return_val_if_fail(param_table, FALSE);
- option_list = (GList*)g_hash_table_lookup(param_table, param_name);
- option_list = g_list_append(option_list, option);
- g_hash_table_insert(param_table, param_name, option_list);
- return TRUE;
-}
-
-GList* qof_object_get_choices(QofIdType type, QofParam *param)
-{
- GList *choices;
- GHashTable *param_table;
-
- g_return_val_if_fail(type != NULL, NULL);
- g_return_val_if_fail(qof_choice_is_initialized() == TRUE, FALSE);
- choices = NULL;
- param_table = g_hash_table_lookup(qof_choice_table, type);
- choices = g_hash_table_lookup(param_table, param->param_name);
- return choices;
-}
-
-gboolean qof_choice_check(char* choice_obj, char *param_name, char* choice )
-{
- GList *choices, *result;
- GHashTable *param_table;
-
- choices = result = NULL;
- g_return_val_if_fail(qof_object_is_choice(choice_obj), FALSE);
- param_table = g_hash_table_lookup(qof_choice_table, choice_obj);
- choices = g_hash_table_lookup(param_table, param_name);
- result = g_list_find(choices, choice);
- if(!result) { return FALSE; }
- return TRUE;
-}
Deleted: gnucash/trunk/src/engine/qofchoice.h
===================================================================
--- gnucash/trunk/src/engine/qofchoice.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofchoice.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,151 +0,0 @@
-/***************************************************************************
- * qofchoice.h
- *
- * Thu Jul 7 12:25:24 2005
- * Copyright 2005 Neil Williams
- * linux at codehelp.co.uk
- ****************************************************************************/
-/*
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _QOFCHOICE_H
-#define _QOFCHOICE_H
-
-/** @addtogroup Choice
-
-Objects can be linked together one-to-one by simply using the name of
-the related object as the parameter type in the QofClass parameter list.
-
-\verbatim
-{ FOO_PARAM, BAR_ID, (QofAccessFunc)qofFooGetBar, (QofSetterFunc)qofFooSetBar },
-\endverbatim
-
-This is limited as each FOO entity can contain only one reference to a
-single BAR entity per parameter. Also, this parameter cannot be used to
-link to a similar object, OBJ. This requires "one to many" links.
-
-There are two types of one-to-many links in QOF.
-
--# ::QOF_TYPE_COLLECT - one to many entities all of only one type.
- - Handles links between one object and a series of objects
- that are \b all of the same type, e.g. a simple list.
--# ::QOF_TYPE_CHOICE - one to a single entity of many possible types.
- - Handles links between one object and a series of
-\b dissimilar objects, one of each type.
-
-Currently, there is no explicit way to support many-to-many links
-but existing methods can be combined to give approximately the same results.
-
-A QOF_TYPE_CHOICE object is like a C++ template. QOF_TYPE_CHOICE doesn't
-really exist by itself:
-\verbatim
-QOF_TYPE_CHOICE<QOF_X, QOF_Y, QOF_Z>
-\endverbatim
-It holds a single entity of type X, Y, or Z for the purposes of QOF
-or ::QSF. For querying the object it queries as if it's an X, Y, or Z.
-
-Each choice type has it's own definition of the allowable objects -
-each of which need to be registered as normal. Objects can declare
-themselves to be one option of a particular choice. There is no
-requirement for any object to be either a choice or an option for a
-choice object.
-
--# Each ::QOF_TYPE_CHOICE parameter provides access to \b ONE entity of
-a pre-determined set of object types.
--# The entity type within the choice can be determined at run time.
--# Each entity can have a different *type* of entity to it's siblings,
-provided that it is one of the pre-determined object types.
--# Objects declare themselves as containing choices and other objects
-can add themselves to the list of acceptable choices of suitable objects.
--# QOF_TYPE_CHOICE is transparent - objects should retrieve the e_type of
-the received entity and handle the entity appropriately.
--# The number of different entity types that can be pre-determined for
-any one QOF_TYPE_CHOICE parameter is not fixed. You can have as many
-types as the ::QofAccessFunc and ::QofSetterFunc can handle.
--# Any one parameter can only have one QOF type. You cannot have a parameter
-that is both ::QOF_TYPE_COLLECT and QOF_TYPE_CHOICE any more than you can have
-one parameter that is both ::QOF_TYPE_BOOLEAN and ::QOF_TYPE_NUMERIC.
--# When setting references using QOF_TYPE_CHOICE, QOF passes a single entity
-to the QofSetterFunc and it is left to the function to determine how to
-handle that entity type. When retrieving references using QOF_TYPE_CHOICE,
-the object must return a single entity matching one of the choice types.
-
- @{
-*/
-
-/** @file qofchoice.h
- @brief Linking one entity to a single entity of many possible types.
- @author Copyright (c) 2005 Neil Williams <linux at codehelp.co.uk>
-*/
-#include "qofclass.h"
-#include "qofobject.h"
-
-/** \brief Identify an object as containing a choice. */
-#define QOF_TYPE_CHOICE "choice"
-
-/** \brief Does this object contain a choice parameter?
-
-Returns TRUE if any parameter in the object definition
-uses a choice of elements, whether or not those
-parameters contain any data.
-
- at param type Type of object/entity.
-
- at return TRUE if one or more choice parameters has been
-registered using the object definition, otherwise FALSE.
-*/
-gboolean qof_object_is_choice(QofIdType type);
-
-/** \brief Set an object as using QOF_TYPE_CHOICE. */
-gboolean qof_choice_create(char* type);
-
-/** \brief Add the choices for this parameter to the object.
-
- at param choice The choice object.
- at param add The object to be added as an option.
- at param param_name The parameter that will be used to get or set options.
-
- at return FALSE if object is not a choice object or on error
- otherwise TRUE.
-*/
-gboolean qof_choice_add_class(char* choice, char* add, char* param_name);
-
-/** \brief Return the list of all object types usable with this parameter.
-
- at param type The choice object type.
- at param param The name of the parameter that will be used to
- get or set options.
-
- at return NULL on error or if no options exist for this parameter,
- otherwise a GList of all QofIdType object type(s) available
- via this choice object using this parameter.
-*/
-GList* qof_object_get_choices(QofIdType type, QofParam *param);
-
-/** \brief Is the choice valid for this param_name?
-
- at param choice_obj The object containing the QOF_TYPE_CHOICE parameter.
- at param param_name The name of a QOF_TYPE_CHOICE parameter in this object.
- at param choice The QofIdType to look for in the list of choices.
-
- at return TRUE if choice is found in the list of allowed choices for
-this parameter of this object. Otherwise, FALSE
-*/
-gboolean qof_choice_check(char* choice_obj, char *param_name, char* choice);
-
-
-/** @} */
-#endif /* _QOFCHOICE_H */
Deleted: gnucash/trunk/src/engine/qofclass-p.h
===================================================================
--- gnucash/trunk/src/engine/qofclass-p.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofclass-p.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,44 +0,0 @@
-/********************************************************************\
- * qofclass-p.h -- Private API for registering queriable objects *
- * Copyright (C) 2002 Derek Atkins <warlord at MIT.EDU> *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-/** @addtogroup Object
- @{ */
-/** @addtogroup Object_Private
- Private interfaces, not meant to be used by applications.
- @{ */
-/** @name Class_Private
- @{ */
-
-#ifndef QOF_CLASSP_H
-#define QOF_CLASSP_H
-
-#include "qofclass.h"
-
-void qof_class_init(void);
-void qof_class_shutdown (void);
-
-QofSortFunc qof_class_get_default_sort (QofIdTypeConst obj_name);
-
-/* @} */
-/* @} */
-/* @} */
-#endif /* QOF_CLASSP_H */
Deleted: gnucash/trunk/src/engine/qofclass.c
===================================================================
--- gnucash/trunk/src/engine/qofclass.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofclass.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,294 +0,0 @@
-/********************************************************************\
- * qofclass.c -- provide QOF paramterized data objects *
- * Copyright (C) 2002 Derek Atkins <warlord at MIT.EDU> *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-#include "config.h"
-
-#include <glib.h>
-
-#include "gnc-trace.h"
-#include "gnc-engine-util.h"
-#include "qofclass.h"
-#include "qofclass-p.h"
-#include "qofquery.h"
-
-static QofLogModule log_module = QOF_MOD_CLASS;
-
-static GHashTable *classTable = NULL;
-static GHashTable *sortTable = NULL;
-static gboolean initialized = FALSE;
-
-static gboolean clear_table (gpointer key, gpointer value, gpointer user_data)
-{
- g_hash_table_destroy (value);
- return TRUE;
-}
-
-/********************************************************************/
-/* PUBLISHED API FUNCTIONS */
-
-void
-qof_class_register (QofIdTypeConst obj_name,
- QofSortFunc default_sort_function,
- const QofParam *params)
-{
- GHashTable *ht;
- int i;
-
- if (!obj_name) return;
-
- if (default_sort_function)
- {
- g_hash_table_insert (sortTable, (char *)obj_name, default_sort_function);
- }
-
- ht = g_hash_table_lookup (classTable, obj_name);
-
- /* If it doesn't already exist, create a new table for this object */
- if (!ht)
- {
- ht = g_hash_table_new (g_str_hash, g_str_equal);
- g_hash_table_insert (classTable, (char *)obj_name, ht);
- }
-
- /* At least right now, we allow dummy, parameterless objects,
- * for testing purposes. Although I suppose that should be
- * an error.. */
- /* Now insert all the parameters */
- if (params)
- {
- for (i = 0; params[i].param_name; i++)
- g_hash_table_insert (ht,
- (char *)params[i].param_name,
- (gpointer)&(params[i]));
- }
-}
-
-void
-qof_class_init(void)
-{
- if (initialized) return;
- initialized = TRUE;
-
- classTable = g_hash_table_new (g_str_hash, g_str_equal);
- sortTable = g_hash_table_new (g_str_hash, g_str_equal);
-}
-
-void
-qof_class_shutdown (void)
-{
- if (!initialized) return;
- initialized = FALSE;
-
- g_hash_table_foreach_remove (classTable, clear_table, NULL);
- g_hash_table_destroy (classTable);
- g_hash_table_destroy (sortTable);
-}
-
-gboolean
-qof_class_is_registered (QofIdTypeConst obj_name)
-{
- if (!obj_name) return FALSE;
-
- if (g_hash_table_lookup (classTable, obj_name)) return TRUE;
-
- return FALSE;
-}
-
-const QofParam *
-qof_class_get_parameter (QofIdTypeConst obj_name,
- const char *parameter)
-{
- GHashTable *ht;
-
- g_return_val_if_fail (obj_name, NULL);
- g_return_val_if_fail (parameter, NULL);
-
- ht = g_hash_table_lookup (classTable, obj_name);
- if (!ht)
- {
- PWARN ("no object of type %s", obj_name);
- return NULL;
- }
-
- return (g_hash_table_lookup (ht, parameter));
-}
-
-QofAccessFunc
-qof_class_get_parameter_getter (QofIdTypeConst obj_name,
- const char *parameter)
-{
- const QofParam *prm;
-
- g_return_val_if_fail (obj_name, NULL);
- g_return_val_if_fail (parameter, NULL);
-
- prm = qof_class_get_parameter (obj_name, parameter);
- if (prm)
- return prm->param_getfcn;
-
- return NULL;
-}
-
-QofSetterFunc
-qof_class_get_parameter_setter (QofIdTypeConst obj_name,
- const char *parameter)
-{
- const QofParam *prm;
-
- g_return_val_if_fail (obj_name, NULL);
- g_return_val_if_fail (parameter, NULL);
-
- prm = qof_class_get_parameter (obj_name, parameter);
- if (prm)
- return prm->param_setfcn;
-
- return NULL;
-}
-
-QofType
-qof_class_get_parameter_type (QofIdTypeConst obj_name,
- const char *param_name)
-{
- const QofParam *prm;
-
- if (!obj_name || !param_name) return NULL;
-
- prm = qof_class_get_parameter (obj_name, param_name);
- if (!prm) return NULL;
-
- return (prm->param_type);
-}
-
-QofSortFunc
-qof_class_get_default_sort (QofIdTypeConst obj_name)
-{
- if (!obj_name) return NULL;
- return g_hash_table_lookup (sortTable, obj_name);
-}
-
-/* ================================================================ */
-
-struct class_iterate {
- QofClassForeachCB fcn;
- gpointer data;
-};
-
-static void
-class_foreach_cb (gpointer key, gpointer item, gpointer arg)
-{
- struct class_iterate *iter = arg;
- QofIdTypeConst id = key;
-
- iter->fcn (id, iter->data);
-}
-
-void
-qof_class_foreach (QofClassForeachCB cb, gpointer user_data)
-{
- struct class_iterate iter;
-
- if (!cb) return;
- if (!classTable) return;
-
- iter.fcn = cb;
- iter.data = user_data;
-
- g_hash_table_foreach (classTable, class_foreach_cb, &iter);
-}
-
-/* ================================================================ */
-
-struct parm_iterate {
- QofParamForeachCB fcn;
- gpointer data;
-};
-
-static void
-param_foreach_cb (gpointer key, gpointer item, gpointer arg)
-{
- struct parm_iterate *iter = arg;
- QofParam *parm = item;
-
- iter->fcn (parm, iter->data);
-}
-
-void
-qof_class_param_foreach (QofIdTypeConst obj_name,
- QofParamForeachCB cb, gpointer user_data)
-{
- struct parm_iterate iter;
- GHashTable *param_ht;
-
- if (!obj_name || !cb) return;
- if (!classTable) return;
- param_ht = g_hash_table_lookup (classTable, obj_name);
- if (!param_ht) return;
-
- iter.fcn = cb;
- iter.data = user_data;
-
- g_hash_table_foreach (param_ht, param_foreach_cb, &iter);
-}
-
-struct param_ref_list
-{
- GList *list;
-};
-
-static void
-find_reference_param_cb(QofParam *param, gpointer user_data)
-{
- struct param_ref_list *b;
-
- b = (struct param_ref_list*)user_data;
- if((param->param_getfcn == NULL)||(param->param_setfcn == NULL)) { return; }
- if(0 == safe_strcmp(param->param_type, QOF_TYPE_STRING)) { return; }
- if(0 == safe_strcmp(param->param_type, QOF_TYPE_NUMERIC)) { return; }
- if(0 == safe_strcmp(param->param_type, QOF_TYPE_DATE)) { return; }
- if(0 == safe_strcmp(param->param_type, QOF_TYPE_CHAR)) { return; }
- if(0 == safe_strcmp(param->param_type, QOF_TYPE_DEBCRED)) { return; }
- if(0 == safe_strcmp(param->param_type, QOF_TYPE_GUID)) { return; }
- if(0 == safe_strcmp(param->param_type, QOF_TYPE_INT32)) { return; }
- if(0 == safe_strcmp(param->param_type, QOF_TYPE_INT64)) { return; }
- if(0 == safe_strcmp(param->param_type, QOF_TYPE_DOUBLE)) { return; }
- if(0 == safe_strcmp(param->param_type, QOF_TYPE_KVP)) { return; }
- if(0 == safe_strcmp(param->param_type, QOF_TYPE_BOOLEAN)) { return; }
- if(0 == safe_strcmp(param->param_type, QOF_ID_BOOK)) { return; }
- b->list = g_list_append(b->list, param);
-}
-
-GList*
-qof_class_get_referenceList(QofIdTypeConst type)
-{
- GList *ref_list;
- struct param_ref_list b;
-
- ref_list = NULL;
- b.list = NULL;
- qof_class_param_foreach(type, find_reference_param_cb, &b);
- ref_list = g_list_copy(b.list);
- return ref_list;
-}
-
-
-/* ============================= END OF FILE ======================== */
Deleted: gnucash/trunk/src/engine/qofclass.h
===================================================================
--- gnucash/trunk/src/engine/qofclass.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofclass.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,268 +0,0 @@
-/********************************************************************\
- * qofclass.h -- API for registering parameters on objects *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-/** @addtogroup Object
- @{ */
-
-/** @addtogroup Class
- This file defines a class messaging system reminiscent of
- traditional OO-style setter and getter interfaces to object
- properties. A C-language object can declare a collection
- of setters and getters on itself that can then be used
- to perform run-time (as opposed to compile-time) bindings
- to the object.
-
- To put it differently, a QOF class is a set of parameter
- getters and setters that are associated with an object type.
- Given a pointer to some thing, the setters and getters can
- be used to get and set values out of that thing. Note
- that the pointer to "some thing" need not be a pointer
- to a QOF Entity or Instance (although QOF classes are
- more interesting when used with Entities/Instances).
- What "some thing" is defined entirely by the programmer
- declaring a new QOF Class.
-
- Because a QOF Class associates getters and setters with
- a type, one can then ask, at run time, what parameters
- are associated with a given type, even if those parameters
- were not known at compile time. Thus, a QOF Class is
- sort-of like a DynAny implementation. QOF classes can
- be used to provide "object introspection", i.e. asking
- object to describe itself.
-
- The QOF Query subsystem depends on QOF classes having been
- declared; the Query uses the getters to get values associated
- with particular instances.
-
- A QofAccessFunc or QofSetterFunc do not need to be public
- functions, if you need to add functions to an object with an
- established API, define the additional QOF routines as static.
- Only the register routine needs to be public.
-@{ */
-
-/** @file qofclass.h
- @brief API for registering paramters on objects
- @author Copyright (C) 2002 Derek Atkins <warlord at MIT.EDU>
- @author Copyright (C) 2003 Linas Vepstas <linas at linas.org>
- @author Copyright (c) 2005 Neil Williams <linux at codehelp.co.uk>
-*/
-
-#ifndef QOF_CLASS_H
-#define QOF_CLASS_H
-
-#include "qofid.h"
-
-#define QOF_MOD_CLASS "qof-class"
-
-/** \name Core types
-
-Core data types for objects that can be used in parameters.
-Note that QofIdTypes may also be used and will create a
-single reference between two known objects.
-
- @{
- */
-
-#define QOF_TYPE_STRING "string"
-#define QOF_TYPE_DATE "date"
-#define QOF_TYPE_NUMERIC "numeric"
-#define QOF_TYPE_DEBCRED "debcred"
-#define QOF_TYPE_GUID "guid"
-#define QOF_TYPE_INT32 "gint32"
-#define QOF_TYPE_INT64 "gint64"
-#define QOF_TYPE_DOUBLE "double"
-#define QOF_TYPE_BOOLEAN "boolean"
-#define QOF_TYPE_KVP "kvp"
-#define QOF_TYPE_CHAR "character"
-#define QOF_TYPE_COLLECT "collection" /**< secondary collections
-are used for one-to-many references between entities and are
-implemented using ::QofCollection.
-These are \b NOT the same as the main collections in the QofBook.
-
--# Each ::QofCollection contains one or many entities - *all* of a single type.
--# The entity type within the collection can be determined at run time.
--# Easy conversions to GList or whatever in the param_setfcn handler.
--# Each parameter can have it's own collection.
--# Each entity can have a different *type* of collection to it's siblings,
-provided that it is acceptable to the set function.
--# Each object decides which types are acceptable for which parameter in the
-set functions. This is then part of the API for that object.
-
-QOF_TYPE_COLLECT has two functions, both related to one-to-many
-links:
-- Represent a reference between 2 entities with a list of acceptable types.
- (one object linked to many types of single entities)
-- Represent a reference between one entity and many entities of another type.
- (one object linked to many entities of a single type.)
-
-If the set function can handle it, it could also be used for true one-to-many
-links: one object linked to many entities of many types.
-
-n.b. Always subject to each collection holding only one type at runtime.
-(otherwise use books).
-
-*/
-/** @} */
-/** Type of Paramters (String, Date, Numeric, GUID, etc.) */
-typedef const char * QofType;
-
-typedef struct _QofParam QofParam;
-
-/** The QofAccessFunc defines an arbitrary function pointer
- * for access functions. This is needed because C doesn't have
- * templates, so we just cast a lot. Real functions must be of
- * the form:
- *
- * param_type getter_func (object_type *self);
- * or
- * param_type getter_func (object_type *self, QofParam *param);
- *
- * The additional argument 'param' allows generic getter functions
- * to be implemented, because this argument provides for a way to
- * identify the expected getter_func return type at runtime. It
- * also provides a place for the user to hang additional user-defined
- * data.
- */
-typedef gpointer (*QofAccessFunc)(gpointer object, const QofParam *param);
-
-/** The QofSetterFunc defines an function pointer for parameter
- * setters. Real functions must be of the form:
- *
- * void setter_func (object_type *self, param_type *param);
- */
-typedef void (*QofSetterFunc) (gpointer, gpointer);
-
-/** This structure is for each queriable parameter in an object
- *
- * -- param_name is the name of the parameter.
- * -- param_type is the type of the parameter, which can be either another
- * object (QofIdType) or it can be a core data type (QofType).
- * -- param_getfcn is the function to actually obtain the parameter
- * -- param_setfcn is the function to actually set the parameter
- * -- param_userdata is a place where the object author can place any
- * desired object-author-defined data (and thus can be used by the
- * author-defined setter/getter).
- *
- * Either the getter or the setter may be NULL.
- *
- * XXX todo/fixme: need to define a destroy callback, so that when
- * the param memory is freed, the callback can be used to release the
- * user-defined data.
- */
-struct _QofParam
-{
- const char * param_name;
- QofType param_type;
- QofAccessFunc param_getfcn;
- QofSetterFunc param_setfcn;
- gpointer param_userdata;
-};
-
-/** This function is the default sort function for a particular object type */
-typedef int (*QofSortFunc)(gpointer, gpointer);
-
-/** This function registers a new object class with the Qof subsystem.
- * In particular, it registers the set of setters and getters for
- * controlling the object. The getters are typically used by the
- * query subsystem to query type specific data. Note that there
- * is no particular requirement for there to be a setter for every
- * getter or even vice-versa, nor is there any requirement for these
- * to map 'cleanly' or orthogonally to the underlying object. The
- * parameters are really just a set of value setting and getting
- * routines.
- *
- * The "params" argument must be a NULL-terminated array of QofParam.
- * It may be NULL if there are no parameters to be registered.
- */
-void qof_class_register (QofIdTypeConst obj_name,
- QofSortFunc default_sort_fcn,
- const QofParam *params);
-
-/** An example:
- *
- * #define MY_OBJ_MEMO "memo"
- * #define MY_OBJ_VALUE "value"
- * #define MY_OBJ_DATE "date"
- * #define MY_OBJ_ACCOUNT "account"
- * #define MY_OBJ_TRANS "trans"
- *
- * static QofParam myParams[] = {
- * { MY_OBJ_MEMO, QOF_TYPE_STRING, myMemoGetter, NULL },
- * { MY_OBJ_VALUE, QOF_TYPE_NUMERIC, myValueGetter, NULL },
- * { MY_OBJ_DATE, QOF_TYPE_DATE, myDateGetter, NULL },
- * { MY_OBJ_ACCOUNT, GNC_ID_ACCOUNT, myAccountGetter, NULL },
- * { MY_OBJ_TRANS, GNC_ID_TRANS, myTransactionGetter, NULL },
- * NULL };
- *
- * qof_class_register ("myObjectName", myObjectCompare, &myParams);
- */
-
-/** Return true if the the indicated type is registered,
- * else return FALSE.
- */
-gboolean qof_class_is_registered (QofIdTypeConst obj_name);
-
-/** Return the core datatype of the specified object's parameter */
-QofType qof_class_get_parameter_type (QofIdTypeConst obj_name,
- const char *param_name);
-
-/** Return the registered Parameter Definition for the requested parameter */
-const QofParam * qof_class_get_parameter (QofIdTypeConst obj_name,
- const char *parameter);
-
-/** Return the object's parameter getter function */
-QofAccessFunc qof_class_get_parameter_getter (QofIdTypeConst obj_name,
- const char *parameter);
-
-/** Return the object's parameter setter function */
-QofSetterFunc qof_class_get_parameter_setter (QofIdTypeConst obj_name,
- const char *parameter);
-
-/** Type definition for the class callback function. */
-typedef void (*QofClassForeachCB) (QofIdTypeConst, gpointer);
-
-/** Call the callback once for each object class that is registered
- * with the system. The 'user_data' is passed back to the callback.
- */
-void qof_class_foreach (QofClassForeachCB, gpointer user_data);
-
-/** Type definition for the paramter callback function. */
-typedef void (*QofParamForeachCB) (QofParam *, gpointer user_data);
-
-/** Call the callback once for each parameter on the indicated
- * object class. The 'user_data' is passed back to the callback.
- */
-void qof_class_param_foreach (QofIdTypeConst obj_name,
- QofParamForeachCB, gpointer user_data);
-
-/** \brief List of the parameters that could be references.
-
-Simple check to return a GList of all parameters
-of this object type that are not known QOF data types.
-Used for partial QofBook support, see ::QofEntityReference
-*/
-GList* qof_class_get_referenceList(QofIdTypeConst type);
-
-
-#endif /* QOF_CLASS_H */
-/** @} */
-/** @} */
Deleted: gnucash/trunk/src/engine/qofgobj.c
===================================================================
--- gnucash/trunk/src/engine/qofgobj.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofgobj.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,326 +0,0 @@
-/********************************************************************\
- * qofgobj.c -- QOF to GLib GObject mapping *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-#include "qof.h"
-#include "qofgobj.h"
-
-static QofLogModule log_module = QOF_MOD_QUERY;
-
-static gboolean initialized = FALSE;
-static GSList *paramList = NULL;
-static GSList *classList = NULL;
-
-/* =================================================================== */
-
-#if 0
-static gboolean
-clear_table (gpointer key, gpointer value, gpointer user_data)
-{
- g_slist_free (value);
- return TRUE;
-}
-#endif
-
-void
-qof_gobject_init(void)
-{
- if (initialized) return;
- initialized = TRUE;
-
- // gobjectClassTable = g_hash_table_new (g_str_hash, g_str_equal);
-
- /* Init the other subsystems that we need */
- qof_object_initialize();
- qof_query_init ();
-}
-
-void
-qof_gobject_shutdown (void)
-{
- GSList *n;
-
- if (!initialized) return;
- initialized = FALSE;
-
-// GSList *n;
- for (n=paramList; n; n=n->next) g_free(n->data);
- g_slist_free (paramList);
-
- for (n=classList; n; n=n->next) g_free(n->data);
- g_slist_free (classList);
-
-#if 0
- // XXX also need to walk over books, and collection and delete
- // the collection get_data instance lists !!
- // without this we have a memory leak !!
- g_hash_table_foreach_remove (gobjectParamTable, clear_table, NULL);
- g_hash_table_destroy (gobjectParamTable);
-#endif
-}
-
-/* =================================================================== */
-
-#define GOBJECT_TABLE "GobjectTable"
-
-void
-qof_gobject_register_instance (QofBook *book, QofType type, GObject *gob)
-{
- QofCollection *coll;
- GSList *instance_list;
-
- if (!book || !type) return;
-
- coll = qof_book_get_collection (book, type);
-
- instance_list = qof_collection_get_data (coll);
- instance_list = g_slist_prepend (instance_list, gob);
- qof_collection_set_data (coll, instance_list);
-}
-
-/* =================================================================== */
-
-static gpointer
-qof_gobject_getter (gpointer data, QofParam *getter)
-{
- GObject *gob = data;
- const char *str;
-
- GParamSpec *gps = getter->param_userdata;
-
- /* Note that the return type must actually be of type
- * getter->param_type but we just follow the hard-coded
- * mapping below ... */
- if (G_IS_PARAM_SPEC_STRING(gps))
- {
- GValue gval = {G_TYPE_INVALID};
- g_value_init (&gval, G_TYPE_STRING);
- g_object_get_property (gob, getter->param_name, &gval);
-
- str = g_value_get_string (&gval);
- return (gpointer) str;
- }
- else
- if (G_IS_PARAM_SPEC_INT(gps))
- {
- int ival;
-
- GValue gval = {G_TYPE_INVALID};
- g_value_init (&gval, G_TYPE_INT);
- g_object_get_property (gob, getter->param_name, &gval);
-
- ival = g_value_get_int (&gval);
- return (gpointer) ival;
- }
- else
- if (G_IS_PARAM_SPEC_UINT(gps))
- {
- int ival;
- GValue gval = {G_TYPE_INVALID};
- g_value_init (&gval, G_TYPE_UINT);
- g_object_get_property (gob, getter->param_name, &gval);
-
- ival = g_value_get_uint (&gval);
- return (gpointer) ival;
- }
- else
- if (G_IS_PARAM_SPEC_BOOLEAN(gps))
- {
- int ival;
-
- GValue gval = {G_TYPE_INVALID};
- g_value_init (&gval, G_TYPE_BOOLEAN);
- g_object_get_property (gob, getter->param_name, &gval);
-
- ival = g_value_get_boolean (&gval);
- return (gpointer) ival;
- }
-
- PWARN ("unhandled parameter type %s for paramter %s",
- G_PARAM_SPEC_TYPE_NAME(gps), getter->param_name);
- return NULL;
-}
-
-static double
-qof_gobject_double_getter (gpointer data, QofParam *getter)
-{
- GObject *gob = data;
- double fval;
-
- GParamSpec *gps = getter->param_userdata;
-
- /* Note that the return type must actually be of type
- * getter->param_type but we just follow the hard-coded
- * mapping below ... */
- if (G_IS_PARAM_SPEC_FLOAT(gps))
- {
- GValue gval = {G_TYPE_INVALID};
- g_value_init (&gval, G_TYPE_FLOAT);
- g_object_get_property (gob, getter->param_name, &gval);
-
- fval = g_value_get_float (&gval);
- return fval;
- }
- else
- if (G_IS_PARAM_SPEC_DOUBLE(gps))
- {
- GValue gval = {G_TYPE_INVALID};
- g_value_init (&gval, G_TYPE_DOUBLE);
- g_object_get_property (gob, getter->param_name, &gval);
-
- fval = g_value_get_double (&gval);
- return fval;
- }
-
- PWARN ("unhandled parameter type %s for paramter %s",
- G_PARAM_SPEC_TYPE_NAME(gps), getter->param_name);
- return 0.0;
-}
-
-/* =================================================================== */
-/* Loop over every instance of the given type in the collection
- * of instances that we have on hand.
- */
-static void
-qof_gobject_foreach (QofCollection *coll, QofEntityForeachCB cb, gpointer ud)
-{
- GSList *n;
- n = qof_collection_get_data (coll);
- for (; n; n=n->next)
- {
- cb (n->data, ud);
- }
-}
-
-/* =================================================================== */
-
-void
-qof_gobject_register (QofType e_type, GObjectClass *obclass)
-{
- int i;
- int j;
- QofParam *qof_param_list, *qpar;
- QofObject *class_def;
- GParamSpec **prop_list, *gparam;
- guint n_props;
-
- /* Get the GObject properties, convert to QOF properties */
- prop_list = g_object_class_list_properties (obclass, &n_props);
-
- qof_param_list = g_new0 (QofParam, n_props);
- paramList = g_slist_prepend (paramList, qof_param_list);
-
- PINFO ("object %s has %d props", e_type, n_props);
- j=0;
- for (i=0; i<n_props; i++)
- {
- gparam = prop_list[i];
- qpar = &qof_param_list[j];
-
- PINFO ("param %d %s is type %s",
- i, gparam->name, G_PARAM_SPEC_TYPE_NAME(gparam));
-
- qpar->param_name = g_param_spec_get_name (gparam);
- qpar->param_getfcn = (QofAccessFunc)qof_gobject_getter;
- qpar->param_setfcn = NULL;
- qpar->param_userdata = gparam;
- if ((G_IS_PARAM_SPEC_INT(gparam)) ||
- (G_IS_PARAM_SPEC_UINT(gparam)) ||
- (G_IS_PARAM_SPEC_ENUM(gparam)) ||
- (G_IS_PARAM_SPEC_FLAGS(gparam)))
- {
- qpar->param_type = QOF_TYPE_INT32;
- j++;
- }
- else
- if ((G_IS_PARAM_SPEC_INT64(gparam)) ||
- (G_IS_PARAM_SPEC_UINT64(gparam)))
- {
- qpar->param_type = QOF_TYPE_INT64;
- j++;
- }
- else
- if (G_IS_PARAM_SPEC_BOOLEAN(gparam))
- {
- qpar->param_type = QOF_TYPE_BOOLEAN;
- j++;
- }
- else
- if (G_IS_PARAM_SPEC_STRING(gparam))
- {
- qpar->param_type = QOF_TYPE_STRING;
- j++;
- }
- else
- if ((G_IS_PARAM_SPEC_POINTER(gparam)) ||
- (G_IS_PARAM_SPEC_OBJECT(gparam)))
- {
- /* No-op, silently ignore. Someday we should handle this ... */
- }
- else
- if ((G_IS_PARAM_SPEC_FLOAT(gparam)) ||
- (G_IS_PARAM_SPEC_DOUBLE(gparam)))
- {
- qpar->param_getfcn = (QofAccessFunc) qof_gobject_double_getter;
- qpar->param_type = QOF_TYPE_DOUBLE;
- j++;
- }
- else
- if (G_IS_PARAM_SPEC_CHAR(gparam))
- {
- qpar->param_type = QOF_TYPE_CHAR;
- j++;
- }
- else
- {
- PWARN ("Unknown/unhandled parameter type %s on %s:%s\n",
- G_PARAM_SPEC_TYPE_NAME(gparam), e_type, qpar->param_name);
- }
- }
-
- /* NULL-terminated list! */
- qof_param_list[j].param_type = NULL;
-
- qof_class_register (e_type, NULL, qof_param_list);
-
- /* ------------------------------------------------------ */
- /* Now do the class itself */
- class_def = g_new0 (QofObject, 1);
- classList = g_slist_prepend (classList, class_def);
-
- class_def->interface_version = QOF_OBJECT_VERSION;
- class_def->e_type = e_type;
- /* We could let the user specify a "nick" here, but
- * the actual class name seems reasonable, e.g. for debugging. */
- class_def->type_label = G_OBJECT_CLASS_NAME (obclass);
- class_def->create = NULL;
- class_def->book_begin = NULL;
- class_def->book_end = NULL;
- class_def->is_dirty = NULL;
- class_def->mark_clean = NULL;
- class_def->foreach = qof_gobject_foreach;
- class_def->printable = NULL;
- class_def->version_cmp = NULL;
-
- qof_object_register (class_def);
-}
-
-/* ======================= END OF FILE ================================ */
Deleted: gnucash/trunk/src/engine/qofgobj.h
===================================================================
--- gnucash/trunk/src/engine/qofgobj.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofgobj.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,87 +0,0 @@
-/********************************************************************\
- * qofgobj.h -- QOF to GLib GObject mapping *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-#ifndef QOF_GOBJ_H
-#define QOF_GOBJ_H
-
-/** @addtogroup Object
- @{ */
-/** @addtogroup GObject GLib GObjects
- The API defined in this file allows a user to register any
- GLib GObject (and any object derived from one, e.g. GTK/Gnome)
- with the QOF system, as a QOF Object Class. This allows
- the QOF Query routines to be used to search over collections
- of GObjects.
-
- XXX Only GObject properties are searchable, data and other
- hanging off the GObject is not. Fix this. This needs fixing.
-
-@{ */
-/** @file qofgobj.h
- @brief QOF to GLib GObject mapping
- @author Copyright (C) 2004 Linas Vepstas <linas at linas.org>
-*/
-
-
-#include <glib-object.h>
-#include "qofbook.h"
-#include "qofclass.h"
-
-/** Initalize and shut down this subsystem. */
-void qof_gobject_init(void);
-void qof_gobject_shutdown (void);
-
-/** Register a GObject class with the QOF subsystem.
- * Doing this will make the properties associated with
- * this GObject searchable using the QOF subsystem.
- *
- * The QofType can be any string you desire, although typically
- * you might want to set it to G_OBJECT_CLASS_NAME() of the
- * object class. Note that this type will become the name of
- * the "table" that is searched by SQL queries:
- * e.g. in order to be able to say "SELECT * FROM MyStuff;"
- * you must first say:
- * qof_gobject_register ("MyStuff", gobj_class);
- */
-void qof_gobject_register (QofType type, GObjectClass *obclass);
-
-/** Register an instance of a GObject with the QOF subsystem.
- *
- * The QofType can be any string you desire, although typically
- * you might want to set it to G_OBJECT_CLASS_NAME() of the
- * object class. Note that this type will become the name of
- * the "table" that is searched by SQL queries:
- * e.g. in order to be able to say "SELECT * FROM MyStuff;"
- * you must first say:
- * qof_gobject_register_instance (book, "MyStuff", obj);
- *
- * The 'book' argument specifies an anchor point for the collection
- * of all of the registered instances. By working with disjoint books,
- * you can have multiple disjoint searchable sets of objects.
- */
-
-void qof_gobject_register_instance (QofBook *book, QofType, GObject *);
-
-#endif /* QOF_GOBJ_H */
-/** @} */
-/** @} */
-
Deleted: gnucash/trunk/src/engine/qofid-p.h
===================================================================
--- gnucash/trunk/src/engine/qofid-p.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofid-p.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,59 +0,0 @@
-/********************************************************************\
- * qofid-p.h -- QOF entity identifier engine-only API *
- * Copyright (C) 2000 Dave Peticolas <peticola at cs.ucdavis.edu> *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-/** @addtogroup Object
- @{ */
-/** @addtogroup Object_Private
- Private interfaces, not meant to be used by applications.
- @{ */
-/** @name Entity_Private
- @{ */
-
-#ifndef QOF_ID_P_H
-#define QOF_ID_P_H
-
-#include <glib.h>
-
-#include "qofid.h"
-
-/* This file defines an engine-only API for using gnucash entity
- * identifiers. */
-
-/** Set the ID of the entity, over-riding teh previous ID.
- * Very dangerous, use only for file i/o work.
- */
-void qof_entity_set_guid (QofEntity *ent, const GUID *guid);
-
-/** Take entity, remove it from whatever collection its currently
- * in, and place it in a new collection. To be used only for
- * moving entity from one book to another.
- */
-void qof_collection_insert_entity (QofCollection *, QofEntity *);
-
-/** reset value of dirty flag */
-void qof_collection_mark_clean (QofCollection *);
-void qof_collection_mark_dirty (QofCollection *);
-
-/* @} */
-/* @} */
-/* @} */
-#endif /* QOF_ID_P_H */
Deleted: gnucash/trunk/src/engine/qofid.c
===================================================================
--- gnucash/trunk/src/engine/qofid.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofid.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,393 +0,0 @@
-/********************************************************************\
- * qofid.c -- QOF entity identifier implementation *
- * Copyright (C) 2000 Dave Peticolas <dave at krondo.com> *
- * Copyright (C) 2003 Linas Vepstas <linas at linas.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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-#include "config.h"
-
-#include <string.h>
-#include <glib.h>
-
-#include "qofid.h"
-#include "qofid-p.h"
-#include "gnc-trace.h"
-#include "gnc-engine-util.h"
-
-static QofLogModule log_module = QOF_MOD_ENGINE;
-
-struct QofCollection_s
-{
- QofIdType e_type;
- gboolean is_dirty;
-
- GHashTable * hash_of_entities;
- gpointer data; /* place where object class can hang arbitrary data */
-};
-
-/* =============================================================== */
-
-static void qof_collection_remove_entity (QofEntity *ent);
-
-void
-qof_entity_init (QofEntity *ent, QofIdType type, QofCollection * tab)
-{
- g_return_if_fail (NULL != tab);
-
- /* XXX We passed redundant info to this routine ... but I think that's
- * OK, it might eliminate programming errors. */
- if (safe_strcmp(tab->e_type, type))
- {
- PERR ("attempt to insert \"%s\" into \"%s\"", type, tab->e_type);
- return;
- }
- ent->e_type = CACHE_INSERT (type);
-
- do
- {
- guid_new(&ent->guid);
-
- if (NULL == qof_collection_lookup_entity (tab, &ent->guid)) break;
-
- PWARN("duplicate id created, trying again");
- } while(1);
-
- ent->collection = tab;
-
- qof_collection_insert_entity (tab, ent);
-}
-
-void
-qof_entity_release (QofEntity *ent)
-{
- if (!ent->collection) return;
- qof_collection_remove_entity (ent);
- CACHE_REMOVE (ent->e_type);
- ent->e_type = NULL;
-}
-
-
-/* This is a restricted function, should be used only during
- * read from file */
-void
-qof_entity_set_guid (QofEntity *ent, const GUID *guid)
-{
- QofCollection *col;
- if (guid_equal (guid, &ent->guid)) return;
-
- col = ent->collection;
- qof_collection_remove_entity (ent);
- ent->guid = *guid;
- qof_collection_insert_entity (col, ent);
-}
-
-const GUID *
-qof_entity_get_guid (QofEntity *ent)
-{
- if (!ent) return guid_null();
- return &ent->guid;
-}
-
-/* =============================================================== */
-
-static guint
-id_hash (gconstpointer key)
-{
- const GUID *guid = key;
-
- if (key == NULL)
- return 0;
-
- /* Compiler should optimize this all away! */
- if (sizeof(guint) <= 16)
- return *((guint *) guid->data);
- else
- {
- guint hash = 0;
- unsigned int i, j;
-
- for (i = 0, j = 0; i < sizeof(guint); i++, j++)
- {
- if (j == 16)
- j = 0;
-
- hash <<= 4;
- hash |= guid->data[j];
- }
-
- return hash;
- }
-}
-
-static gboolean
-id_compare(gconstpointer key_1, gconstpointer key_2)
-{
- return guid_equal (key_1, key_2);
-}
-
-QofCollection *
-qof_collection_new (QofIdType type)
-{
- QofCollection *col;
- col = g_new0(QofCollection, 1);
- col->e_type = CACHE_INSERT (type);
- col->hash_of_entities = g_hash_table_new (id_hash, id_compare);
- col->data = NULL;
- return col;
-}
-
-void
-qof_collection_destroy (QofCollection *col)
-{
- CACHE_REMOVE (col->e_type);
- g_hash_table_destroy(col->hash_of_entities);
- col->e_type = NULL;
- col->hash_of_entities = NULL;
- col->data = NULL; /** XXX there should be a destroy notifier for this */
- g_free (col);
-}
-
-/* =============================================================== */
-/* getters */
-
-QofIdType
-qof_collection_get_type (QofCollection *col)
-{
- return col->e_type;
-}
-
-/* =============================================================== */
-
-static void
-qof_collection_remove_entity (QofEntity *ent)
-{
- QofCollection *col;
- if (!ent) return;
- col = ent->collection;
- if (!col) return;
- g_hash_table_remove (col->hash_of_entities, &ent->guid);
- ent->collection = NULL;
-}
-
-void
-qof_collection_insert_entity (QofCollection *col, QofEntity *ent)
-{
- if (!col || !ent) return;
- if (guid_equal(&ent->guid, guid_null())) return;
- g_return_if_fail (col->e_type == ent->e_type);
- qof_collection_remove_entity (ent);
- g_hash_table_insert (col->hash_of_entities, &ent->guid, ent);
- ent->collection = col;
-}
-
-gboolean
-qof_collection_add_entity (QofCollection *coll, QofEntity *ent)
-{
- QofEntity *e;
-
- e = NULL;
- if (!coll || !ent) { return FALSE; }
- if (guid_equal(&ent->guid, guid_null())) { return FALSE; }
- g_return_val_if_fail (coll->e_type == ent->e_type, FALSE);
- e = qof_collection_lookup_entity(coll, &ent->guid);
- if ( e != NULL ) { return FALSE; }
- g_hash_table_insert (coll->hash_of_entities, &ent->guid, ent);
- return TRUE;
-}
-
-static void
-collection_merge_cb (QofEntity *ent, gpointer data)
-{
- QofCollection *target;
-
- target = (QofCollection*)data;
- qof_collection_add_entity(target, ent);
-}
-
-gboolean
-qof_collection_merge (QofCollection *target, QofCollection *merge)
-{
- if(!target || !merge) { return FALSE; }
- g_return_val_if_fail (target->e_type == merge->e_type, FALSE);
- qof_collection_foreach(merge, collection_merge_cb, target);
- return TRUE;
-}
-
-static void
-collection_compare_cb (QofEntity *ent, gpointer user_data)
-{
- QofCollection *target;
- QofEntity *e;
- gint value;
-
- e = NULL;
- target = (QofCollection*)user_data;
- if (!target || !ent) { return; }
- value = *(gint*)qof_collection_get_data(target);
- if (value != 0) { return; }
- if (guid_equal(&ent->guid, guid_null()))
- {
- value = -1;
- qof_collection_set_data(target, &value);
- return;
- }
- g_return_if_fail (target->e_type == ent->e_type);
- e = qof_collection_lookup_entity(target, &ent->guid);
- if ( e == NULL )
- {
- value = 1;
- qof_collection_set_data(target, &value);
- return;
- }
- value = 0;
- qof_collection_set_data(target, &value);
-}
-
-gint
-qof_collection_compare (QofCollection *target, QofCollection *merge)
-{
- gint value;
-
- value = 0;
- if (!target && !merge) { return 0; }
- if (target == merge) { return 0; }
- if (!target && merge) { return -1; }
- if (target && !merge) { return 1; }
- if(target->e_type != merge->e_type) { return -1; }
- qof_collection_set_data(target, &value);
- qof_collection_foreach(merge, collection_compare_cb, target);
- value = *(gint*)qof_collection_get_data(target);
- if(value == 0) {
- qof_collection_set_data(merge, &value);
- qof_collection_foreach(target, collection_compare_cb, merge);
- value = *(gint*)qof_collection_get_data(merge);
- }
- return value;
-}
-
-QofEntity *
-qof_collection_lookup_entity (QofCollection *col, const GUID * guid)
-{
- QofEntity *ent;
- g_return_val_if_fail (col, NULL);
- if (guid == NULL) return NULL;
- ent = g_hash_table_lookup (col->hash_of_entities, guid->data);
- return ent;
-}
-
-QofCollection *
-qof_collection_from_glist (QofIdType type, GList *glist)
-{
- QofCollection *coll;
- QofEntity *ent;
- GList *list;
-
- coll = qof_collection_new(type);
- for(list = glist; list != NULL; list = list->next)
- {
- ent = (QofEntity*)list->data;
- if(FALSE == qof_collection_add_entity(coll, ent))
- {
- return NULL;
- }
- }
- return coll;
-}
-
-guint
-qof_collection_count (QofCollection *col)
-{
- guint c;
-
- c = g_hash_table_size(col->hash_of_entities);
- return c;
-}
-
-/* =============================================================== */
-
-gboolean
-qof_collection_is_dirty (QofCollection *col)
-{
- if (!col) return FALSE;
- return col->is_dirty;
-}
-
-void
-qof_collection_mark_clean (QofCollection *col)
-{
- if (!col) return;
- col->is_dirty = FALSE;
-}
-
-void
-qof_collection_mark_dirty (QofCollection *col)
-{
- if (!col) return;
- col->is_dirty = TRUE;
-}
-
-/* =============================================================== */
-
-gpointer
-qof_collection_get_data (QofCollection *col)
-{
- if (!col) return NULL;
- return col->data;
-}
-
-void
-qof_collection_set_data (QofCollection *col, gpointer user_data)
-{
- if (!col) return;
- col->data = user_data;
-}
-
-/* =============================================================== */
-
-struct _iterate {
- QofEntityForeachCB fcn;
- gpointer data;
-};
-
-static void foreach_cb (gpointer key, gpointer item, gpointer arg)
-{
- struct _iterate *iter = arg;
- QofEntity *ent = item;
-
- iter->fcn (ent, iter->data);
-}
-
-void
-qof_collection_foreach (QofCollection *col,
- QofEntityForeachCB cb_func, gpointer user_data)
-{
- struct _iterate iter;
-
- g_return_if_fail (col);
- g_return_if_fail (cb_func);
-
- iter.fcn = cb_func;
- iter.data = user_data;
-
- g_hash_table_foreach (col->hash_of_entities, foreach_cb, &iter);
-}
-
-/* =============================================================== */
Deleted: gnucash/trunk/src/engine/qofid.h
===================================================================
--- gnucash/trunk/src/engine/qofid.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofid.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,264 +0,0 @@
-/********************************************************************\
- * qofid.h -- QOF entity type identification system *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-#ifndef QOF_ID_H
-#define QOF_ID_H
-
-/** @addtogroup Entity
- @{ */
-/** @addtogroup Entities
-
- This file defines an API that adds types to the GUID's.
- GUID's with types can be used to identify and reference
- typed entities.
-
- The idea here is that a GUID can be used to uniquely identify
- some thing. By adding a type, one can then talk about the
- type of thing identified. By adding a collection, one can
- then work with a handle to a collection of things of a given
- type, each uniquely identified by a given ID. QOF Entities
- can be used independently of any other part of the system.
- In particular, Entities can be useful even if one is not using
- the Query ond Object parts of the QOF system.
-
- Identifiers are globally-unique and permanent, i.e., once
- an entity has been assigned an identifier, it retains that same
- identifier for its lifetime.
- Identifiers can be encoded as hex strings.
-
- GUID Identifiers are 'typed' with strings. The native ids used
- by QOF are defined below. An id with type QOF_ID_NONE does not
- refer to any entity, although that may change (???). An id with
- type QOF_ID_NULL does not refer to any entity, and will never refer
- to any entity. An identifier with any other type may refer to an
- actual entity, but that is not guaranteed (??? Huh?). If an id
- does refer to an entity, the type of the entity will match the
- type of the identifier.
-
- If you have a type name, and you want to have a way of finding
- a collection that is associated with that type, then you must use
- Books.
-
- Entities can refer to other entities as well as to the basic
- QOF types, using the qofclass parameters.
-
- @{ */
-/** @file qofid.h
- @brief QOF entity type identification system
- @author Copyright (C) 2000 Dave Peticolas <peticola at cs.ucdavis.edu>
- @author Copyright (C) 2003 Linas Vepstas <linas at linas.org>
-*/
-
-#include <string.h>
-#include "guid.h"
-
-/** QofIdType declaration */
-typedef const char * QofIdType;
-/** QofIdTypeConst declaration */
-typedef const char * QofIdTypeConst;
-/** QofLogModule declaration */
-typedef const gchar* QofLogModule;
-
-#define QOF_ID_NONE NULL
-#define QOF_ID_NULL "null"
-
-#define QOF_ID_BOOK "Book"
-#define QOF_ID_SESSION "Session"
-
-/** simple,cheesy cast but holds water for now */
-#define QOF_ENTITY(object) ((QofEntity *)(object))
-
-/** Inline string comparision; compiler will optimize away most of this */
-#define QSTRCMP(da,db) ({ \
- int val = 0; \
- if ((da) && (db)) { \
- if ((da) != (db)) { \
- val = strcmp ((da), (db)); \
- } \
- } else \
- if ((!(da)) && (db)) { \
- val = -1; \
- } else \
- if ((da) && (!(db))) { \
- val = 1; \
- } \
- val; /* block assumes value of last statment */ \
-})
-
-/** return TRUE if object is of the given type */
-#define QOF_CHECK_TYPE(obj,type) (0 == QSTRCMP((type),(((QofEntity *)(obj))->e_type)))
-
-/** cast object to the indicated type, print error message if its bad */
-#define QOF_CHECK_CAST(obj,e_type,c_type) ( \
- QOF_CHECK_TYPE((obj),(e_type)) ? \
- (c_type *) (obj) : \
- (c_type *) ({ \
- g_log (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, \
- "Error: Bad QofEntity at %s:%d", __FILE__, __LINE__); \
- (obj); \
- }))
-
-/** QofEntity declaration */
-typedef struct QofEntity_s QofEntity;
-/** QofCollection declaration
-
- at param e_type QofIdType
- at param is_dirty gboolean
- at param hash_of_entities GHashTable
- at param data gpointer, place where object class can hang arbitrary data
-
-*/
-typedef struct QofCollection_s QofCollection;
-
-/** QofEntity structure
-
- at param e_type Entity type
- at param guid GUID for the entity
- at param collection Entity collection
-*/
-
-struct QofEntity_s
-{
- QofIdType e_type;
- GUID guid;
- QofCollection * collection;
-};
-
-/** @name QOF Entity Initialization & Shutdown
- @{ */
-/** Initialise the memory associated with an entity */
-void qof_entity_init (QofEntity *, QofIdType, QofCollection *);
-
-/** Release the data associated with this entity. Dont actually free
- * the memory associated with the instance. */
-void qof_entity_release (QofEntity *);
-/** @} */
-
-/** Return the GUID of this entity */
-const GUID * qof_entity_get_guid (QofEntity *);
-
-/** @name Collections of Entities
- @{ */
-
-/** create a new collection of entities of type */
-QofCollection * qof_collection_new (QofIdType type);
-
-/** return the number of entities in the collection. */
-guint qof_collection_count (QofCollection *col);
-
-/** destroy the collection */
-void qof_collection_destroy (QofCollection *col);
-
-/** return the type that the collection stores */
-QofIdType qof_collection_get_type (QofCollection *);
-
-/** Find the entity going only from its guid */
-QofEntity * qof_collection_lookup_entity (QofCollection *, const GUID *);
-
-/** Callback type for qof_entity_foreach */
-typedef void (*QofEntityForeachCB) (QofEntity *, gpointer user_data);
-
-/** Call the callback for each entity in the collection. */
-void qof_collection_foreach (QofCollection *,
- QofEntityForeachCB, gpointer user_data);
-
-/** Store and retreive arbitrary object-defined data
- *
- * XXX We need to add a callback for when the collection is being
- * destroyed, so that the user has a chance to clean up anything
- * that was put in the 'data' member here.
- */
-gpointer qof_collection_get_data (QofCollection *col);
-void qof_collection_set_data (QofCollection *col, gpointer user_data);
-
-/** Return value of 'dirty' flag on collection */
-gboolean qof_collection_is_dirty (QofCollection *col);
-
-/** @name QOF_TYPE_COLLECT: Linking one entity to many of one type
-
-\note These are \b NOT the same as the main collections in the book.
-
-QOF_TYPE_COLLECT is a secondary collection, used to select entities
-of one object type as references of another entity.
-\sa QOF_TYPE_CHOICE.
-
-@{
-*/
-/** \brief Add an entity to a QOF_TYPE_COLLECT.
-
-\note These are \b NOT the same as the main collections in the book.
-
-Entities can be
-freely added and merged across these secondary collections, they
-will not be removed from the original collection as they would
-by using ::qof_entity_insert_entity or ::qof_entity_remove_entity.
-
-*/
-gboolean
-qof_collection_add_entity (QofCollection *coll, QofEntity *ent);
-
-/** \brief Merge two QOF_TYPE_COLLECT of the same type.
-
-\note \b NOT the same as the main collections in the book.
-
-QOF_TYPE_COLLECT uses a secondary collection, independent of
-those in the book. Entities will not be removed from the
-original collection as when using ::qof_entity_insert_entity
-or ::qof_entity_remove_entity.
-
-*/
-gboolean
-qof_collection_merge (QofCollection *target, QofCollection *merge);
-
-/** \brief Compare two secondary collections.
-
-Performs a deep comparision of the collections. Each QofEntity in
-each collection is looked up in the other collection, via the GUID.
-
-\return 0 if the collections are identical or both are NULL
-otherwise -1 if target is NULL or either collection contains an entity with an invalid
-GUID or if the types of the two collections do not match,
-or +1 if merge is NULL or if any entity exists in one collection but
-not in the other.
-*/
-gint
-qof_collection_compare (QofCollection *target, QofCollection *merge);
-
-/** \brief Create a secondary collection from a GList
-
- at param type The QofIdType of the QofCollection \b and of
- \b all entities in the GList.
- at param glist GList of entities of the same QofIdType.
-
- at return NULL if any of the entities fail to match the
- QofCollection type, else a pointer to the collection
- on success.
-*/
-QofCollection*
-qof_collection_from_glist (QofIdType type, GList *glist);
-
-/** @} */
-/** @} */
-
-#endif /* QOF_ID_H */
-/** @} */
-/** @} */
Deleted: gnucash/trunk/src/engine/qofinstance-p.h
===================================================================
--- gnucash/trunk/src/engine/qofinstance-p.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofinstance-p.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,97 +0,0 @@
-/********************************************************************\
- * qofinstance-p.h -- private fields common to all object instances *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-/*
- * Object instance holds many common fields that most
- * gnucash objects use.
- *
- * Copyright (C) 2003 Linas Vepstas <linas at linas.org>
- */
-
-/** @addtogroup Object
- @{ */
-/** @addtogroup Object_Private
- Private interfaces, not meant to be used by applications.
- @{ */
-/** @name Instance_Private
- @{ */
-
-#ifndef QOF_INSTANCE_P_H
-#define QOF_INSTANCE_P_H
-
-#include "qofinstance.h"
-
-/**
- * UNDER CONSTRUCTION!
- * This is mostly scaffolding for now,
- * eventually, it may hold more fields, such as refrence counting...
- *
- */
-struct QofInstance_s
-{
- /** Globally unique id identifying this instance */
- QofEntity entity;
-
- /** The entity_table in which this instance is stored */
- QofBook * book;
-
- /** kvp_data is a key-value pair database for storing arbirtary
- * information associated with this instance.
- * See src/engine/kvp_doc.txt for a list and description of the
- * important keys. */
- KvpFrame *kvp_data;
-
- /** Timestamp used to track the last modification to this
- * instance. Typically used to compare two versions of the
- * same object, to see which is newer. When used with the
- * SQL backend, this field is reserved for SQL use, to compare
- * the version in local memory to the remote, server version.
- */
- Timespec last_update;
-
- /** Keep track of nesting level of begin/end edit calls */
- int editlevel;
-
- /** In process of being destroyed */
- gboolean do_free;
-
- /** dirty/clean flag. If dirty, then this instance has been modified,
- * but has not yet been written out to storage (file/database)
- */
- gboolean dirty;
-};
-
-/** reset the dirty flag */
-void qof_instance_mark_clean (QofInstance *);
-
-void qof_instance_set_slots (QofInstance *, KvpFrame *);
-
-/** Set the last_update time. Reserved for use by the SQL backend;
- * used for comparing version in local memory to that in remote
- * server.
- */
-void qof_instance_set_last_update (QofInstance *inst, Timespec ts);
-
-/* @} */
-/* @} */
-/* @} */
-
-#endif /* QOF_INSTANCE_P_H */
Deleted: gnucash/trunk/src/engine/qofinstance.c
===================================================================
--- gnucash/trunk/src/engine/qofinstance.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofinstance.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,245 +0,0 @@
-/********************************************************************\
- * qofinstance.c -- handler for fields common to all objects *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-/*
- * Object instance holds many common fields that most
- * gnucash objects use.
- *
- * Copyright (C) 2003 Linas Vepstas <linas at linas.org>
- */
-
-#include "gnc-trace.h"
-
-#include "kvp-util-p.h"
-#include "qofbook.h"
-#include "qofbook-p.h"
-#include "qofid.h"
-#include "qofid-p.h"
-#include "qofinstance.h"
-#include "qofinstance-p.h"
-
-static QofLogModule log_module = QOF_MOD_ENGINE;
-
-/* ========================================================== */
-
-QofInstance*
-qof_instance_create (QofIdType type, QofBook *book)
-{
- QofInstance *inst;
-
- inst = g_new0(QofInstance, 1);
- qof_instance_init(inst, type, book);
- return inst;
-}
-
-void
-qof_instance_init (QofInstance *inst, QofIdType type, QofBook *book)
-{
- QofCollection *col;
-
- inst->book = book;
- inst->kvp_data = kvp_frame_new();
- inst->last_update.tv_sec = 0;
- inst->last_update.tv_nsec = -1;
- inst->editlevel = 0;
- inst->do_free = FALSE;
- inst->dirty = FALSE;
-
- col = qof_book_get_collection (book, type);
- qof_entity_init (&inst->entity, type, col);
-}
-
-void
-qof_instance_release (QofInstance *inst)
-{
- kvp_frame_delete (inst->kvp_data);
- inst->editlevel = 0;
- inst->do_free = FALSE;
- inst->dirty = FALSE;
- qof_entity_release (&inst->entity);
-}
-
-const GUID *
-qof_instance_get_guid (QofInstance *inst)
-{
- if (!inst) return NULL;
- return &inst->entity.guid;
-}
-
-QofBook *
-qof_instance_get_book (QofInstance *inst)
-{
- if (!inst) return NULL;
- return inst->book;
-}
-
-KvpFrame*
-qof_instance_get_slots (QofInstance *inst)
-{
- if (!inst) return NULL;
- return inst->kvp_data;
-}
-
-Timespec
-qof_instance_get_last_update (QofInstance *inst)
-{
- if (!inst)
- {
- Timespec ts = {0,-1};
- return ts;
- }
- return inst->last_update;
-}
-
-int
-qof_instance_version_cmp (QofInstance *left, QofInstance *right)
-{
- if (!left && !right) return 0;
- if (!left) return -1;
- if (!right) return +1;
- if (left->last_update.tv_sec < right->last_update.tv_sec) return -1;
- if (left->last_update.tv_sec > right->last_update.tv_sec) return +1;
- if (left->last_update.tv_nsec < right->last_update.tv_nsec) return -1;
- if (left->last_update.tv_nsec > right->last_update.tv_nsec) return +1;
- return 0;
-}
-
-gboolean
-qof_instance_is_dirty (QofInstance *inst)
-{
- QofCollection *coll;
-
- if (!inst) { return FALSE; }
- coll = inst->entity.collection;
- if(qof_collection_is_dirty(coll)) { return inst->dirty; }
- inst->dirty = FALSE;
- return FALSE;
-}
-
-void
-qof_instance_set_dirty(QofInstance* inst)
-{
- QofCollection *coll;
-
- inst->dirty = TRUE;
- coll = inst->entity.collection;
- qof_collection_mark_dirty(coll);
-}
-
-gboolean
-qof_instance_check_edit(QofInstance *inst)
-{
- if(inst->editlevel > 0) { return TRUE; }
- return FALSE;
-}
-
-gboolean
-qof_instance_do_free(QofInstance *inst)
-{
- return inst->do_free;
-}
-
-void
-qof_instance_mark_free(QofInstance *inst)
-{
- inst->do_free = TRUE;
-}
-
-/* ========================================================== */
-/* setters */
-
-void
-qof_instance_mark_clean (QofInstance *inst)
-{
- if(!inst) return;
- inst->dirty = FALSE;
-}
-
-void
-qof_instance_set_slots (QofInstance *inst, KvpFrame *frm)
-{
- if (!inst) return;
- if (inst->kvp_data && (inst->kvp_data != frm))
- {
- kvp_frame_delete(inst->kvp_data);
- }
-
- inst->dirty = TRUE;
- inst->kvp_data = frm;
-}
-
-void
-qof_instance_set_last_update (QofInstance *inst, Timespec ts)
-{
- if (!inst) return;
- inst->last_update = ts;
-}
-
-/* ========================================================== */
-
-void
-qof_instance_gemini (QofInstance *to, QofInstance *from)
-{
- time_t now;
-
- /* Books must differ for a gemini to be meaningful */
- if (!from || !to || (from->book == to->book)) return;
-
- now = time(0);
-
- /* Make a note of where the copy came from */
- gnc_kvp_bag_add (to->kvp_data, "gemini", now,
- "inst_guid", &from->entity.guid,
- "book_guid", &from->book->inst.entity.guid,
- NULL);
- gnc_kvp_bag_add (from->kvp_data, "gemini", now,
- "inst_guid", &to->entity.guid,
- "book_guid", &to->book->inst.entity.guid,
- NULL);
-
- to->dirty = TRUE;
-}
-
-QofInstance *
-qof_instance_lookup_twin (QofInstance *src, QofBook *target_book)
-{
- QofCollection *col;
- KvpFrame *fr;
- GUID * twin_guid;
- QofInstance * twin;
-
- if (!src || !target_book) return NULL;
- ENTER (" ");
-
- fr = gnc_kvp_bag_find_by_guid (src->kvp_data, "gemini",
- "book_guid", &target_book->inst.entity.guid);
-
- twin_guid = kvp_frame_get_guid (fr, "inst_guid");
-
- col = qof_book_get_collection (target_book, src->entity.e_type);
- twin = (QofInstance *) qof_collection_lookup_entity (col, twin_guid);
-
- LEAVE (" found twin=%p", twin);
- return twin;
-}
-
-/* ========================== END OF FILE ======================= */
Deleted: gnucash/trunk/src/engine/qofinstance.h
===================================================================
--- gnucash/trunk/src/engine/qofinstance.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofinstance.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,130 +0,0 @@
-/********************************************************************\
- * qofinstance.h -- fields common to all object instances *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-/** @addtogroup Entity
- @{ */
-/** @addtogroup Instance
- Qof Instances are a derived type of QofEntity. The Instance
- adds some common features and functions that most objects
- will want to use.
-
- @{ */
-/** @file qofinstance.h
- * @brief Object instance holds common fields that most gnucash objects use.
- *
- * @author Copyright (C) 2003,2004 Linas Vepstas <linas at linas.org>
- */
-
-#ifndef QOF_INSTANCE_H
-#define QOF_INSTANCE_H
-
-#include "guid.h"
-#include "gnc-date.h"
-#include "kvp_frame.h"
-#include "qofbook.h"
-#include "qofid.h"
-
-/* --- type macros --- */
-/* cheesy, but will do for now, eventually should be more gtk-like, handle
- * thunks, etc. */
-#define QOF_INSTANCE(object) ((QofInstance *)(object))
-
-typedef struct QofInstance_s QofInstance;
-
-/** Initialise the memory associated with an instance */
-void qof_instance_init (QofInstance *, QofIdType, QofBook *);
-
-/** release the data associated with this instance. Dont actually free
- * the memory associated with the instance. */
-void qof_instance_release (QofInstance *inst);
-
-/** Return the book pointer */
-QofBook * qof_instance_get_book (QofInstance *);
-
-/** Return the GUID of this instance */
-const GUID * qof_instance_get_guid (QofInstance *);
-
-/** Return the pointer to the kvp_data */
-KvpFrame* qof_instance_get_slots (QofInstance *);
-
-/** Return the last time this instance was modified. If QofInstances
- * are used with the QofObject storage backends, then the instance
- * update times are reserved for use by the backend, for managing
- * multi-user updates. Non-backend code should not set the update
- * times.
- */
-Timespec qof_instance_get_last_update (QofInstance *inst);
-
-/** Compare two instances, based on thier last update times.
- * Returns a negative, zero or positive value, respectively,
- * if 'left' is earlier, same as or later than 'right'.
- * Accepts NULL pointers, NULL's are by definition earlier
- * than any value.
- */
-int qof_instance_version_cmp (QofInstance *left, QofInstance *right);
-
-/** Return value of is_dirty flag */
-gboolean qof_instance_is_dirty (QofInstance *);
-
-/** \brief Set the dirty flag
-
-Sets this instance AND the collection as dirty.
-*/
-void qof_instance_set_dirty(QofInstance* inst);
-
-gboolean qof_instance_check_edit(QofInstance *inst);
-
-gboolean qof_instance_do_free(QofInstance *inst);
-
-void qof_instance_mark_free(QofInstance *inst);
-
-QofInstance* qof_instance_create (QofIdType type, QofBook *book);
-
-/** Pair things up. This routine inserts a kvp value into each instance
- * containing the guid of the other. In this way, if one has one of the
- * pair, one can always find the other by looking up it's guid. Typically,
- * you will want to use qof_instance_lookup_twin() to find the twin.
- * (The current implementation assumes the two instances belong to different
- * books, and will not add gemini kvp's unless the books differ. Note that
- * the gemini kvp includes the book guid as well, so that the right book can
- * be found.
- */
-void qof_instance_gemini (QofInstance *to, QofInstance *from);
-
-/** The qof_instance_lookup_twin() routine will find the "twin" of this
- * instance 'src' in the given other 'book' (if the twin exists).
- *
- * When instances are gemini'ed or cloned, both of the pair are marked
- * with the guid of thier copy, thus allowing the sibling-copy of
- * an instance to be found. Since the sibling may end up in a
- * different book, we need a way of finding it, given only that we
- * know the book, and that we know its twin.
- *
- * That's what this routine does. Given some book 'book', and an
- * instance 'src', it will find the sibling instance of 'src' that is
- * in 'book', and return it. If not found, it returns NULL. This
- * routine uses the 'gemini' kvp values to do its work.
- */
-QofInstance * qof_instance_lookup_twin (QofInstance *src, QofBook *book);
-
-/* @} */
-/* @} */
-#endif /* QOF_INSTANCE_H */
Deleted: gnucash/trunk/src/engine/qofla-dir.h.in
===================================================================
--- gnucash/trunk/src/engine/qofla-dir.h.in 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofla-dir.h.in 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,26 +0,0 @@
-/***************************************************************************
- * qofla-dir.h.in
- *
- * Mon Dec 20 20:27:48 2004
- * Copyright 2004 Neil Williams
- * linux at codehelp.co.uk
- ****************************************************************************/
-
-/*
- * 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 Library General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#define QOF_LIB_DIR "@-libdir-@"
-
Deleted: gnucash/trunk/src/engine/qofmath128.c
===================================================================
--- gnucash/trunk/src/engine/qofmath128.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofmath128.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,408 +0,0 @@
-/********************************************************************
- * qofmath128.c -- an 128-bit integer library *
- * Copyright (C) 2004 Linas Vepstas <linas at linas.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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
- *******************************************************************/
-
-#define _GNU_SOURCE
-
-#include "config.h"
-#include "qofmath128.h"
-
-#include <glib.h>
-
-/* =============================================================== */
-/*
- * Quick-n-dirty 128-bit integer math lib. Things seem to mostly
- * work, and have been tested, but not comprehensively tested.
- */
-
-#define HIBIT (0x8000000000000000ULL)
-
-/** Multiply a pair of signed 64-bit numbers,
- * returning a signed 128-bit number.
- */
-inline qofint128
-mult128 (gint64 a, gint64 b)
-{
- qofint128 prod;
- guint64 a0, a1;
- guint64 b0, b1;
- guint64 d, d0, d1;
- guint64 e, e0, e1;
- guint64 f, f0, f1;
- guint64 g, g0, g1;
- guint64 sum, carry, roll, pmax;
-
- prod.isneg = 0;
- if (0>a)
- {
- prod.isneg = !prod.isneg;
- a = -a;
- }
-
- if (0>b)
- {
- prod.isneg = !prod.isneg;
- b = -b;
- }
-
- a1 = a >> 32;
- a0 = a - (a1<<32);
-
- b1 = b >> 32;
- b0 = b - (b1<<32);
-
- d = a0*b0;
- d1 = d >> 32;
- d0 = d - (d1<<32);
-
- e = a0*b1;
- e1 = e >> 32;
- e0 = e - (e1<<32);
-
- f = a1*b0;
- f1 = f >> 32;
- f0 = f - (f1<<32);
-
- g = a1*b1;
- g1 = g >> 32;
- g0 = g - (g1<<32);
-
- sum = d1+e0+f0;
- carry = 0;
- /* Can't say 1<<32 cause cpp will goof it up; 1ULL<<32 might work */
- roll = 1<<30;
- roll <<= 2;
-
- pmax = roll-1;
- while (pmax < sum)
- {
- sum -= roll;
- carry ++;
- }
-
- prod.lo = d0 + (sum<<32);
- prod.hi = carry + e1 + f1 + g0 + (g1<<32);
- // prod.isbig = (prod.hi || (sum >> 31));
- prod.isbig = prod.hi || (prod.lo >> 63);
-
- return prod;
-}
-
-/** Shift right by one bit (i.e. divide by two) */
-inline qofint128
-shift128 (qofint128 x)
-{
- guint64 sbit = x.hi & 0x1;
- x.hi >>= 1;
- x.lo >>= 1;
- x.isbig = 0;
- if (sbit)
- {
- x.lo |= HIBIT;
- x.isbig = 1;
- return x;
- }
- if (x.hi)
- {
- x.isbig = 1;
- }
- return x;
-}
-
-/** Shift leftt by one bit (i.e. multiply by two) */
-inline qofint128
-shiftleft128 (qofint128 x)
-{
- guint64 sbit;
- sbit = x.lo & HIBIT;
- x.hi <<= 1;
- x.lo <<= 1;
- x.isbig = 0;
- if (sbit)
- {
- x.hi |= 1;
- x.isbig = 1;
- return x;
- }
- if (x.hi)
- {
- x.isbig = 1;
- }
- return x;
-}
-
-/** increment a 128-bit number by one */
-inline qofint128
-inc128 (qofint128 a)
-{
- if (0 == a.isneg)
- {
- a.lo ++;
- if (0 == a.lo)
- {
- a.hi ++;
- }
- }
- else
- {
- if (0 == a.lo)
- {
- a.hi --;
- }
- a.lo --;
- }
-
- a.isbig = (a.hi != 0) || (a.lo >> 63);
- return a;
-}
-
-/** Divide a signed 128-bit number by a signed 64-bit,
- * returning a signed 128-bit number.
- */
-inline qofint128
-div128 (qofint128 n, gint64 d)
-{
- qofint128 quotient;
- int i;
- guint64 remainder = 0;
-
- quotient = n;
- if (0 > d)
- {
- d = -d;
- quotient.isneg = !quotient.isneg;
- }
-
- /* Use grade-school long division algorithm */
- for (i=0; i<128; i++)
- {
- guint64 sbit = HIBIT & quotient.hi;
- remainder <<= 1;
- if (sbit) remainder |= 1;
- quotient = shiftleft128 (quotient);
- if (remainder >= d)
- {
- remainder -= d;
- quotient.lo |= 1;
- }
- }
-
- /* compute the carry situation */
- quotient.isbig = (quotient.hi || (quotient.lo >> 63));
-
- return quotient;
-}
-
-/** Return the remainder of a signed 128-bit number modulo
- * a signed 64-bit. That is, return n%d in 128-bit math.
- * I beleive that ths algo is overflow-free, but should be
- * audited some more ...
- */
-inline gint64
-rem128 (qofint128 n, gint64 d)
-{
- qofint128 quotient = div128 (n,d);
-
- qofint128 mu = mult128 (quotient.lo, d);
-
- gint64 nn = 0x7fffffffffffffffULL & n.lo;
- gint64 rr = 0x7fffffffffffffffULL & mu.lo;
- return nn - rr;
-}
-
-/** Return true of two numbers are equal */
-inline gboolean
-equal128 (qofint128 a, qofint128 b)
-{
- if (a.lo != b.lo) return 0;
- if (a.hi != b.hi) return 0;
- if (a.isneg != b.isneg) return 0;
- return 1;
-}
-
-/** Return returns 1 if a>b, -1 if b>a, 0 if a == b */
-inline int
-cmp128 (qofint128 a, qofint128 b)
-{
- if ((0 == a.isneg) && b.isneg) return 1;
- if (a.isneg && (0 == b.isneg)) return -1;
- if (0 == a.isneg)
- {
- if (a.hi > b.hi) return 1;
- if (a.hi < b.hi) return -1;
- if (a.lo > b.lo) return 1;
- if (a.lo < b.lo) return -1;
- return 0;
- }
-
- if (a.hi > b.hi) return -1;
- if (a.hi < b.hi) return 1;
- if (a.lo > b.lo) return -1;
- if (a.lo < b.lo) return 1;
- return 0;
-}
-
-/** Return the greatest common factor of two 64-bit numbers */
-inline guint64
-gcf64(guint64 num, guint64 denom)
-{
- guint64 t;
-
- t = num % denom;
- num = denom;
- denom = t;
-
- /* The strategy is to use Euclid's algorithm */
- while (0 != denom)
- {
- t = num % denom;
- num = denom;
- denom = t;
- }
- /* num now holds the GCD (Greatest Common Divisor) */
- return num;
-}
-
-/** Return the least common multiple of two 64-bit numbers. */
-inline qofint128
-lcm128 (guint64 a, guint64 b)
-{
- guint64 gcf = gcf64 (a,b);
- b /= gcf;
- return mult128 (a,b);
-}
-
-/** Add a pair of 128-bit numbers, returning a 128-bit number */
-inline qofint128
-add128 (qofint128 a, qofint128 b)
-{
- qofint128 sum;
- if (a.isneg == b.isneg)
- {
- sum.isneg = a.isneg;
- sum.hi = a.hi + b.hi;
- sum.lo = a.lo + b.lo;
- if ((sum.lo < a.lo) || (sum.lo < b.lo))
- {
- sum.hi ++;
- }
- sum.isbig = sum.hi || (sum.lo >> 63);
- return sum;
- }
- if ((b.hi > a.hi) ||
- ((b.hi == a.hi) && (b.lo > a.lo)))
- {
- qofint128 tmp = a;
- a = b;
- b = tmp;
- }
-
- sum.isneg = a.isneg;
- sum.hi = a.hi - b.hi;
- sum.lo = a.lo - b.lo;
-
- if (sum.lo > a.lo)
- {
- sum.hi --;
- }
-
- sum.isbig = sum.hi || (sum.lo >> 63);
- return sum;
-}
-
-
-#ifdef TEST_128_BIT_MULT
-static void pr (gint64 a, gint64 b)
-{
- qofint128 prod = mult128 (a,b);
- printf ("%" G_GINT64_FORMAT " * %" G_GINT64_FORMAT " = %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT " (0x%llx %llx) %hd\n",
- a, b, prod.hi, prod.lo, prod.hi, prod.lo, prod.isbig);
-}
-
-static void prd (gint64 a, gint64 b, gint64 c)
-{
- qofint128 prod = mult128 (a,b);
- qofint128 quot = div128 (prod, c);
- gint64 rem = rem128 (prod, c);
- printf ("%" G_GINT64_FORMAT " * %" G_GINT64_FORMAT " / %" G_GINT64_FORMAT " = %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT " + %" G_GINT64_FORMAT " (0x%llx %llx) %hd\n",
- a, b, c, quot.hi, quot.lo, rem, quot.hi, quot.lo, quot.isbig);
-}
-
-int main ()
-{
- pr (2,2);
-
- gint64 x = 1<<30;
- x <<= 2;
-
- pr (x,x);
- pr (x+1,x);
- pr (x+1,x+1);
-
- pr (x,-x);
- pr (-x,-x);
- pr (x-1,x);
- pr (x-1,x-1);
- pr (x-2,x-2);
-
- x <<= 1;
- pr (x,x);
- pr (x,-x);
-
- pr (1000000, 10000000000000);
-
- prd (x,x,2);
- prd (x,x,3);
- prd (x,x,4);
- prd (x,x,5);
- prd (x,x,6);
-
- x <<= 29;
- prd (3,x,3);
- prd (6,x,3);
- prd (99,x,3);
- prd (100,x,5);
- prd (540,x,5);
- prd (777,x,7);
- prd (1111,x,11);
-
- /* Really test division */
- qofint128 n;
- n.hi = 0xdd91;
- n.lo = 0x6c5abefbb9e13480ULL;
-
- gint64 d = 0x2ae79964d3ae1d04ULL;
-
- int i;
- for (i=0; i<20; i++) {
-
- qofint128 quot = div128 (n, d);
- printf ("%d result = %llx %llx\n", i, quot.hi, quot.lo);
- d >>=1;
- n = shift128 (n);
- }
- return 0;
-}
-
-#endif /* TEST_128_BIT_MULT */
-
-/* ======================== END OF FILE =================== */
Deleted: gnucash/trunk/src/engine/qofmath128.h
===================================================================
--- gnucash/trunk/src/engine/qofmath128.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofmath128.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,85 +0,0 @@
-/********************************************************************
- * qofmath128.h -- an 128-bit integer library *
- * Copyright (C) 2004 Linas Vepstas <linas at linas.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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
- *******************************************************************/
-
-#ifndef QOF_MATH_128_H
-#define QOF_MATH_128_H
-
-#include <glib.h>
-
-/** @addtogroup Math128
- * Quick-n-dirty 128-bit integer math lib. Things seem to mostly
- * work, and have been tested, but not comprehensively tested.
- * @{
- */
-
-typedef struct {
- guint64 hi;
- guint64 lo;
- short isneg; /**< sign-bit -- T if number is negative */
- short isbig; /**< sizeflag -- T if number won't fit in signed 64-bit */
-} qofint128;
-
-/** Return true of two numbers are equal */
-inline gboolean equal128 (qofint128 a, qofint128 b);
-
-/** Return returns 1 if a>b, -1 if b>a, 0 if a == b */
-inline int cmp128 (qofint128 a, qofint128 b);
-
-/** Shift right by one bit (i.e. divide by two) */
-inline qofint128 shift128 (qofint128 x);
-
-/** Shift left by one bit (i.e. multiply by two) */
-inline qofint128 shiftleft128 (qofint128 x);
-
-/** Increment by one */
-inline qofint128 inc128 (qofint128 a);
-
-/** Add a pair of 128-bit numbers, returning a 128-bit number */
-inline qofint128 add128 (qofint128 a, qofint128 b);
-
-/** Multiply a pair of signed 64-bit numbers,
- * returning a signed 128-bit number.
- */
-inline qofint128 mult128 (gint64 a, gint64 b);
-
-/** Divide a signed 128-bit number by a signed 64-bit,
- * returning a signed 128-bit number.
- */
-inline qofint128 div128 (qofint128 n, gint64 d);
-
-/** Return the remainder of a signed 128-bit number modulo
- * a signed 64-bit. That is, return n%d in 128-bit math.
- * I beleive that ths algo is overflow-free, but should be
- * audited some more ...
- */
-inline gint64 rem128 (qofint128 n, gint64 d);
-
-/** Return the greatest common factor of two 64-bit numbers */
-inline guint64 gcf64(guint64 num, guint64 denom);
-
-/** Return the least common multiple of two 64-bit numbers. */
-inline qofint128 lcm128 (guint64 a, guint64 b);
-
-#endif
-
-/** @} */
Deleted: gnucash/trunk/src/engine/qofobject-p.h
===================================================================
--- gnucash/trunk/src/engine/qofobject-p.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofobject-p.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,49 +0,0 @@
-/********************************************************************\
- * qofobject-p.h -- the private Object Registration/Lookup Interface *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-/** @addtogroup Object
- @{ */
-/** @addtogroup Object_Private
- Private interfaces, not meant to be used by applications.
- @{ */
-/** @name Objects_Private
- @{ */
-/** @file qofobject-p.h
- * @brief the Core Object Registration/Lookup Private Interface
- * @author Copyright (c) 2001,2002, Derek Atkins <warlord at MIT.EDU>
- */
-
-#ifndef QOF_OBJECT_P_H_
-#define QOF_OBJECT_P_H_
-
-#include "qofbook.h"
-#include "qofobject.h"
-
-/** To be called from within the book */
-void qof_object_book_begin (QofBook *book);
-void qof_object_book_end (QofBook *book);
-
-gboolean qof_object_is_dirty (QofBook *book);
-void qof_object_mark_clean (QofBook *book);
-
-#endif /* QOF_OBJECT_P_H_ */
-/** @} */
-/** @} */
-/** @} */
Deleted: gnucash/trunk/src/engine/qofobject.c
===================================================================
--- gnucash/trunk/src/engine/qofobject.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofobject.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,353 +0,0 @@
-/********************************************************************\
- * qofobject.c -- the Core Object Registration/Lookup Interface *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-/*
- * qofobject.c -- the Core Object Object Registry
- * Copyright (C) 2001 Derek Atkins
- * Author: Derek Atkins <warlord at MIT.EDU>
- */
-
-#include "config.h"
-
-#include <glib.h>
-
-#include "gnc-trace.h"
-#include "gnc-engine-util.h"
-#include "qofobject.h"
-#include "qofobject-p.h"
-#include "qofbook.h"
-
-static QofLogModule log_module = QOF_MOD_OBJECT;
-
-static gboolean object_is_initialized = FALSE;
-static GList *object_modules = NULL;
-static GList *book_list = NULL;
-static GHashTable *backend_data = NULL;
-
-gpointer
-qof_object_new_instance (QofIdTypeConst type_name, QofBook *book)
-{
- const QofObject *obj;
-
- if (!type_name) return NULL;
-
- obj = qof_object_lookup (type_name);
- if (!obj) return NULL;
-
- if (obj->create)
- return (obj->create (book));
-
- return NULL;
-}
-
-void qof_object_book_begin (QofBook *book)
-{
- GList *l;
-
- if (!book) return;
- ENTER (" ");
- for (l = object_modules; l; l = l->next) {
- QofObject *obj = l->data;
- if (obj->book_begin)
- obj->book_begin (book);
- }
-
- /* Remember this book for later */
- book_list = g_list_prepend (book_list, book);
- LEAVE (" ");
-}
-
-void qof_object_book_end (QofBook *book)
-{
- GList *l;
-
- if (!book) return;
- ENTER (" ");
- for (l = object_modules; l; l = l->next) {
- QofObject *obj = l->data;
- if (obj->book_end)
- obj->book_end (book);
- }
-
- /* Remove it from the list */
- book_list = g_list_remove (book_list, book);
- LEAVE (" ");
-}
-
-gboolean
-qof_object_is_dirty (QofBook *book)
-{
- GList *l;
-
- if (!book) return FALSE;
- for (l = object_modules; l; l = l->next)
- {
- QofObject *obj = l->data;
- if (obj->is_dirty)
- {
- QofCollection *col;
- col = qof_book_get_collection (book, obj->e_type);
- if (obj->is_dirty (col)) return TRUE;
- }
- }
- return FALSE;
-}
-
-void
-qof_object_mark_clean (QofBook *book)
-{
- GList *l;
-
- if (!book) return;
- for (l = object_modules; l; l = l->next)
- {
- QofObject *obj = l->data;
- if (obj->mark_clean)
- {
- QofCollection *col;
- col = qof_book_get_collection (book, obj->e_type);
- (obj->mark_clean) (col);
- }
- }
-}
-
-void qof_object_foreach_type (QofForeachTypeCB cb, gpointer user_data)
-{
- GList *l;
-
- if (!cb) return;
-
- for (l = object_modules; l; l = l->next) {
- QofObject *obj = l->data;
- (cb) (obj, user_data);
- }
-}
-
-void
-qof_object_foreach (QofIdTypeConst type_name, QofBook *book,
- QofEntityForeachCB cb, gpointer user_data)
-{
- QofCollection *col;
- const QofObject *obj;
-
- if (!book || !type_name) return;
- ENTER ("type=%s", type_name);
-
- obj = qof_object_lookup (type_name);
- if (!obj)
- {
- PERR ("No object of type %s", type_name);
- return;
- }
- col = qof_book_get_collection (book, obj->e_type);
- PINFO ("lookup obj=%p for type=%s", obj, type_name);
- if (!obj) return;
-
- PINFO ("type=%s foreach=%p", type_name, obj->foreach);
- if (obj->foreach)
- {
- obj->foreach (col, cb, user_data);
- }
- LEAVE ("type=%s", type_name);
-
- return;
-}
-
-const char *
-qof_object_printable (QofIdTypeConst type_name, gpointer obj)
-{
- const QofObject *b_obj;
-
- if (!type_name || !obj) return NULL;
-
- b_obj = qof_object_lookup (type_name);
- if (!b_obj) return NULL;
-
- if (b_obj->printable)
- return (b_obj->printable (obj));
-
- return NULL;
-}
-
-const char * qof_object_get_type_label (QofIdTypeConst type_name)
-{
- const QofObject *obj;
-
- if (!type_name) return NULL;
-
- obj = qof_object_lookup (type_name);
- if (!obj) return NULL;
-
- return (obj->type_label);
-}
-
-static gboolean clear_table (gpointer key, gpointer value, gpointer user_data)
-{
- g_hash_table_destroy (value);
- return TRUE;
-}
-
-/* INITIALIZATION and PRIVATE FUNCTIONS */
-
-void qof_object_initialize (void)
-{
- if (object_is_initialized) return;
- backend_data = g_hash_table_new (g_str_hash, g_str_equal);
- object_is_initialized = TRUE;
-}
-
-void qof_object_shutdown (void)
-{
- g_return_if_fail (object_is_initialized == TRUE);
-
- g_hash_table_foreach_remove (backend_data, clear_table, NULL);
- g_hash_table_destroy (backend_data);
- backend_data = NULL;
-
- g_list_free (object_modules);
- object_modules = NULL;
- g_list_free (book_list);
- book_list = NULL;
- object_is_initialized = FALSE;
-}
-
-/* Register new types of object objects.
- * Return TRUE if successful,
- * return FALSE if it fails, invalid arguments, or if the object
- * already exists
- */
-gboolean qof_object_register (const QofObject *object)
-{
- g_return_val_if_fail (object_is_initialized, FALSE);
-
- if (!object) return FALSE;
- g_return_val_if_fail (object->interface_version == QOF_OBJECT_VERSION, FALSE);
-
- if (g_list_index (object_modules, (gpointer)object) == -1)
- object_modules = g_list_prepend (object_modules, (gpointer)object);
- else
- return FALSE;
-
- /* Now initialize all the known books */
- if (object->book_begin && book_list) {
- GList *node;
- for (node = book_list; node; node = node->next)
- object->book_begin (node->data);
- }
-
- return TRUE;
-}
-
-const QofObject * qof_object_lookup (QofIdTypeConst name)
-{
- GList *iter;
- const QofObject *obj;
-
- g_return_val_if_fail (object_is_initialized, NULL);
-
- if (!name) return NULL;
-
- for (iter = object_modules; iter; iter = iter->next) {
- obj = iter->data;
- if (!safe_strcmp (obj->e_type, name))
- return obj;
- }
- return NULL;
-}
-
-gboolean qof_object_register_backend (QofIdTypeConst type_name,
- const char *backend_name,
- gpointer be_data)
-{
- GHashTable *ht;
- g_return_val_if_fail (object_is_initialized, FALSE);
-
- if (!type_name || *type_name == '\0' ||
- !backend_name || *backend_name == '\0' ||
- !be_data)
- return FALSE;
-
- ht = g_hash_table_lookup (backend_data, backend_name);
-
- /* If it doesn't already exist, create a new table for this backend */
- if (!ht) {
- ht = g_hash_table_new (g_str_hash, g_str_equal);
- g_hash_table_insert (backend_data, (char *)backend_name, ht);
- }
-
- /* Now insert the data */
- g_hash_table_insert (ht, (char *)type_name, be_data);
-
- return TRUE;
-}
-
-gpointer qof_object_lookup_backend (QofIdTypeConst type_name,
- const char *backend_name)
-{
- GHashTable *ht;
-
- if (!type_name || *type_name == '\0' ||
- !backend_name || *backend_name == '\0')
- return NULL;
-
- ht = g_hash_table_lookup (backend_data, (char *)backend_name);
- if (!ht)
- return NULL;
-
- return g_hash_table_lookup (ht, (char *)type_name);
-}
-
-struct foreach_data {
- QofForeachBackendTypeCB cb;
- gpointer user_data;
-};
-
-static void foreach_backend (gpointer key, gpointer be_item, gpointer arg)
-{
- char *data_type = key;
- struct foreach_data *cb_data = arg;
-
- g_return_if_fail (key && be_item && arg);
-
- /* Call the callback for this data type */
- (cb_data->cb) (data_type, be_item, cb_data->user_data);
-}
-
-void qof_object_foreach_backend (const char *backend_name,
- QofForeachBackendTypeCB cb,
- gpointer user_data)
-{
- GHashTable *ht;
- struct foreach_data cb_data;
-
- if (!backend_name || *backend_name == '\0' || !cb)
- return;
-
- ht = g_hash_table_lookup (backend_data, (char *)backend_name);
- if (!ht)
- return;
-
- cb_data.cb = cb;
- cb_data.user_data = user_data;
-
- g_hash_table_foreach (ht, foreach_backend, &cb_data);
-}
-
-/* ========================= END OF FILE =================== */
Deleted: gnucash/trunk/src/engine/qofobject.h
===================================================================
--- gnucash/trunk/src/engine/qofobject.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofobject.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,179 +0,0 @@
-/********************************************************************\
- * qofobject.h -- the Core Object Registration/Lookup Interface *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-/** @addtogroup Object
- @{ */
-/** @addtogroup Objects
- QOF Objects provide the means for associating
- a storage backend to a set of QOF Entities. While an entity
- can be though of as an identified instance of some thing, the
- QOF Object provides for a way to associate instances with
- a storage backend. Storage might be file or SQL storage.
-
- QOF Objects are also used by the query system ....
-
- To work with your own QOF Objects, you can use the QOF
- Generator to create sample objects and a mini-application
- with the SQL-type query interface.
- http://qof-gen.sourceforge.net/
-
- XXX todo, we should split out the storage aspects of this
- thing from the 'foreach' that query depends on. These are
- kinda unrelated concepts.
-
- @{ */
-/** @file qofobject.h
- * @brief the Core Object Registration/Lookup Interface
- * @author Copyright (c) 2001,2002 Derek Atkins <warlord at MIT.EDU>
- */
-
-#ifndef QOF_OBJECT_H_
-#define QOF_OBJECT_H_
-
-#include "qofbook.h"
-#include "qofid.h"
-#include "qofchoice.h"
-
-/** Defines the version of the core object object registration
- * interface. Only object modules compiled against this version
- * of the interface will load properly
- */
-#define QOF_OBJECT_VERSION 3
-
-#define QOF_MOD_OBJECT "qof-object"
-
-typedef struct _QofObject QofObject;
-typedef void (*QofForeachCB) (gpointer obj, gpointer user_data);
-typedef void (*QofForeachTypeCB) (QofObject *type, gpointer user_data);
-typedef void (*QofForeachBackendTypeCB) (QofIdTypeConst type,
- gpointer backend_data,
- gpointer user_data);
-
-/** This is the QofObject Class descriptor
- */
-struct _QofObject
-{
- gint interface_version; /* of this object interface */
- QofIdType e_type; /* the Object's QOF_ID */
- const char * type_label; /* "Printable" type-label string */
-
- /** Create a new instance of this object type. This routine might be
- * NULL if the object type doesn't provide a way of creating new
- * instances.
- */
- gpointer (*create)(QofBook *);
-
- /** book_begin is called from within the Book routines to create
- * module-specific hooks in a book whenever a book is created.
- */
- void (*book_begin)(QofBook *);
-
- /** book_end is called when the book is being closed, to clean
- * up (and free memory).
- */
- void (*book_end)(QofBook *);
-
- /** Determine if there are any dirty items in this book */
- gboolean (*is_dirty)(QofCollection *);
-
- /** Mark this object's book clean (for after a load) */
- void (*mark_clean)(QofCollection *);
-
- /** Traverse over all of the items in the collection, calling
- * the callback on each item. The third argument can be any
- * arbitrary caller-supplied data, and is passed to the callback.
- * Although (*foreach) may be NULL, allmost all objects should
- * provide this routine, as without it, little of interest can
- * be done.
- */
- void (*foreach)(QofCollection *, QofEntityForeachCB, gpointer);
-
- /** Given a particular item of this type, return a printable string.
- */
- const char * (*printable)(gpointer instance);
-
- /** Given a pair of items of this type, this routine returns value
- * indicating which item is 'newer'. This routine is used by storage
- * backends to determine if the local or the remote copy of a
- * particular item is the latest, 'uptodate' version. Tis routine
- * should return an integer less than, equal to, or greater than zero
- * if 'instance_left' is found to be, respecitvely, earlier than, equal
- * to or later than than 'instance_right'.
- */
- int (*version_cmp)(gpointer instance_left, gpointer instance_right);
-};
-
-/* -------------------------------------------------------------- */
-
-/** @name Initialize the object registration subsystem */
-/** @{ */
-void qof_object_initialize (void);
-void qof_object_shutdown (void);
-/** @} */
-
-/** Register new types of object objects */
-gboolean qof_object_register (const QofObject *object);
-
-/** Lookup an object definition */
-const QofObject * qof_object_lookup (QofIdTypeConst type_name);
-
-/** Create an instance of the indicated type, returning a pointer to that
- * instance. This routine just calls the (*new) callback on the object
- * definition.
- */
-gpointer qof_object_new_instance (QofIdTypeConst type_name, QofBook *book);
-
-/** Get the printable label for a type. This label is *not*
- * translated; you must use _() on it if you want a translated version.
- */
-const char * qof_object_get_type_label (QofIdTypeConst type_name);
-
-/** @return a Human-readable string name for an instance */
-const char * qof_object_printable (QofIdTypeConst type_name, gpointer instance);
-
-/** Invoke the callback 'cb' on every object class definition.
- * The user_data pointer is passed back to the callback.
- */
-void qof_object_foreach_type (QofForeachTypeCB cb, gpointer user_data);
-
-/** Invoke the callback 'cb' on every instance ov a particular
- * object type. It is presumed that the 'book' stores or somehow
- * identifies a colllection of instances; thus the callback will
- * be invoked only for those instances stored in the book.
- */
-void qof_object_foreach (QofIdTypeConst type_name, QofBook *book,
- QofEntityForeachCB cb, gpointer user_data);
-
-/** Register and lookup backend-specific data for this particular object */
-gboolean qof_object_register_backend (QofIdTypeConst type_name,
- const char *backend_name,
- gpointer be_data);
-
-gpointer qof_object_lookup_backend (QofIdTypeConst type_name,
- const char *backend_name);
-
-void qof_object_foreach_backend (const char *backend_name,
- QofForeachBackendTypeCB cb,
- gpointer user_data);
-
-#endif /* QOF_OBJECT_H_ */
-/** @} */
-/** @} */
Deleted: gnucash/trunk/src/engine/qofquery-deserial.c
===================================================================
--- gnucash/trunk/src/engine/qofquery-deserial.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofquery-deserial.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,756 +0,0 @@
-/********************************************************************\
- * qofquery-deserial.c -- Convert Qof-Query XML to QofQuery *
- * Copyright (C) 2001,2002,2004 Linas Vepstas <linas at linas.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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-// #include "config.h"
-
-#include <stdlib.h>
-#include <glib.h>
-#include <libxml/parser.h>
-
-#include "qofquery-deserial.h"
-#include "qofquery-serialize.h"
-#include "qofquery-p.h"
-#include "qofquerycore-p.h"
-#include "gnc-engine-util.h"
-
-/* =========================================================== */
-
-#define GET_TEXT(node) ({ \
- char * sstr = NULL; \
- xmlNodePtr text; \
- text = node->xmlChildrenNode; \
- if (text && 0 == strcmp ("text", text->name)) { \
- sstr = text->content; \
- } \
- sstr; \
-})
-
-#define GET_STR(SELF,FN,TOK) \
- if (0 == strcmp (TOK, node->name)) \
- { \
- const char *str = GET_TEXT (node); \
- FN (SELF, str); \
- } \
- else
-
-#define GET_DBL(SELF,FN,TOK) \
- if (0 == strcmp (TOK, node->name)) \
- { \
- const char *str = GET_TEXT (node); \
- double rate = atof (str); \
- FN (SELF, rate); \
- } \
- else
-
-#define GET_INT32(SELF,FN,TOK) \
- if (0 == strcmp (TOK, node->name)) \
- { \
- const char *str = GET_TEXT (node); \
- gint32 ival = atoi (str); \
- FN (SELF, ival); \
- } \
- else
-
-#define GET_INT64(SELF,FN,TOK) \
- if (0 == strcmp (TOK, node->name)) \
- { \
- const char *str = GET_TEXT (node); \
- gint64 ival = atoll (str); \
- FN (SELF, ival); \
- } \
- else
-
-#define GET_DATE(SELF,FN,TOK) \
- if (0 == strcmp (TOK, node->name)) \
- { \
- const char *str = GET_TEXT (node); \
- Timespec tval = gnc_iso8601_to_timespec_gmt (str); \
- FN (SELF, tval); \
- } \
- else
-
-#define GET_BOOL(SELF,FN,TOK) \
- if (0 == strcmp (TOK, node->name)) \
- { \
- const char *str = GET_TEXT (node); \
- gboolean bval = qof_util_bool_to_int (str); \
- FN (SELF, bval); \
- } \
- else
-
-#define GET_NUMERIC(SELF,FN,TOK) \
- if (0 == strcmp (TOK, node->name)) \
- { \
- const char *str = GET_TEXT (node); \
- gnc_numeric nval; \
- string_to_gnc_numeric (str, &nval); \
- FN (SELF, nval); \
- } \
- else
-
-#define GET_GUID(SELF,FN,TOK) \
- if (0 == strcmp (TOK, node->name)) \
- { \
- const char *str = GET_TEXT (node); \
- GUID guid; \
- string_to_guid (str, &guid); \
- FN (SELF, &guid); \
- } \
- else
-
-#define GET_HOW(VAL,TOK,A,B,C,D,E,F) \
- if (0 == strcmp (TOK, node->name)) \
- { \
- const char *str = GET_TEXT (node); \
- int ival = QOF_COMPARE_##A; \
- if (!strcmp (#A, str)) ival = QOF_COMPARE_##A; \
- else if (!strcmp (#B, str)) ival = QOF_COMPARE_##B; \
- else if (!strcmp (#C, str)) ival = QOF_COMPARE_##C; \
- else if (!strcmp (#D, str)) ival = QOF_COMPARE_##D; \
- else if (!strcmp (#E, str)) ival = QOF_COMPARE_##E; \
- else if (!strcmp (#F, str)) ival = QOF_COMPARE_##F; \
- VAL = ival; \
- } \
- else
-
-#define GET_MATCH2(VAL,TOK,PFX,A,B) \
- if (0 == strcmp (TOK, node->name)) \
- { \
- const char *str = GET_TEXT (node); \
- int ival = QOF_##PFX##_##A; \
- if (!strcmp (#A, str)) ival = QOF_##PFX##_##A; \
- else if (!strcmp (#B, str)) ival = QOF_##PFX##_##B; \
- VAL = ival; \
- } \
- else
-
-#define GET_MATCH3(VAL,TOK,PFX,A,B,C) \
- if (0 == strcmp (TOK, node->name)) \
- { \
- const char *str = GET_TEXT (node); \
- int ival = QOF_##PFX##_##A; \
- if (!strcmp (#A, str)) ival = QOF_##PFX##_##A; \
- else if (!strcmp (#B, str)) ival = QOF_##PFX##_##B; \
- else if (!strcmp (#C, str)) ival = QOF_##PFX##_##C; \
- VAL = ival; \
- } \
- else
-
-#define GET_MATCH5(VAL,TOK,PFX,A,B,C,D,E) \
- if (0 == strcmp (TOK, node->name)) \
- { \
- const char *str = GET_TEXT (node); \
- int ival = QOF_##PFX##_##A; \
- if (!strcmp (#A, str)) ival = QOF_##PFX##_##A; \
- else if (!strcmp (#B, str)) ival = QOF_##PFX##_##B; \
- else if (!strcmp (#C, str)) ival = QOF_##PFX##_##C; \
- else if (!strcmp (#D, str)) ival = QOF_##PFX##_##D; \
- else if (!strcmp (#E, str)) ival = QOF_##PFX##_##E; \
- VAL = ival; \
- } \
- else
-
-/* =============================================================== */
-/* Autogen the code for the simple, repetitive predicates */
-
-#define SIMPLE_PRED_HANDLER(SUBRNAME,CTYPE,GETTER,XMLTYPE,PRED) \
-static QofQueryPredData * \
-SUBRNAME (xmlNodePtr root) \
-{ \
- QofQueryPredData *pred; \
- xmlNodePtr xp; \
- xmlNodePtr node; \
- QofQueryCompare how; \
- CTYPE val; \
- xp = root->xmlChildrenNode; \
- \
- how = QOF_COMPARE_EQUAL; \
- val = 0; \
- \
- for (node=xp; node; node = node->next) \
- { \
- if (node->type != XML_ELEMENT_NODE) continue; \
- \
- GET_HOW (how, "qofquery:compare", LT, LTE, EQUAL, GT, GTE, NEQ); \
- GETTER (0, val=, XMLTYPE); \
- {} \
- } \
- \
- pred = PRED (how, val); \
- return pred; \
-}
-
-SIMPLE_PRED_HANDLER (qof_query_pred_double_from_xml,
- double,
- GET_DBL,
- "qofquery:double",
- qof_query_double_predicate);
-
-SIMPLE_PRED_HANDLER (qof_query_pred_int64_from_xml,
- gint64,
- GET_INT64,
- "qofquery:int64",
- qof_query_int64_predicate);
-
-SIMPLE_PRED_HANDLER (qof_query_pred_int32_from_xml,
- gint32,
- GET_INT32,
- "qofquery:int32",
- qof_query_int32_predicate);
-
-SIMPLE_PRED_HANDLER (qof_query_pred_boolean_from_xml,
- gboolean,
- GET_BOOL,
- "qofquery:boolean",
- qof_query_boolean_predicate);
-
-/* =============================================================== */
-
-static void wrap_new_gint64(KvpValue **v, gint64 value) {
- *v = kvp_value_new_gint64 (value); }
-static void wrap_new_double(KvpValue **v, double value) {
- *v = kvp_value_new_double (value); }
-static void wrap_new_numeric(KvpValue **v, gnc_numeric value) {
- *v = kvp_value_new_gnc_numeric (value); }
-static void wrap_new_string(KvpValue **v, const char * value) {
- *v = kvp_value_new_string (value); }
-static void wrap_new_guid(KvpValue **v, const GUID * value) {
- *v = kvp_value_new_guid (value); }
-static void wrap_new_timespec(KvpValue **v, Timespec value) {
- *v = kvp_value_new_timespec (value); }
-
-
-static QofQueryPredData *
-qof_query_pred_kvp_from_xml (xmlNodePtr root)
-{
- QofQueryCompare how;
- GSList *path;
- KvpValue *value;
- QofQueryPredData *pred;
- xmlNodePtr xp;
- xmlNodePtr node;
-
- how = QOF_COMPARE_EQUAL;
- xp = root->xmlChildrenNode;
- path = NULL;
- value = NULL;
-
- for (node=xp; node; node = node->next)
- {
- if (node->type != XML_ELEMENT_NODE) continue;
-
- GET_HOW (how, "qofquery:compare", LT, LTE, EQUAL, GT, GTE, NEQ);
- if (0 == strcmp ("qofquery:kvp-path", node->name))
- {
- const char *str = GET_TEXT (node);
- path = g_slist_append (path, (gpointer) str);
- }
- else
- GET_INT64(&value, wrap_new_gint64, "qofquery:int64");
- GET_DBL(&value, wrap_new_double, "qofquery:double");
- GET_NUMERIC(&value, wrap_new_numeric, "qofquery:numeric");
- GET_STR(&value, wrap_new_string, "qofquery:string");
- GET_GUID(&value, wrap_new_guid, "qofquery:guid");
- GET_DATE(&value, wrap_new_timespec, "qofquery:date");
- }
-
- pred = qof_query_kvp_predicate (how, path, value);
- g_slist_free (path);
- return pred;
-}
-
-/* =============================================================== */
-
-static QofQueryPredData *
-qof_query_pred_guid_from_xml (xmlNodePtr root)
-{
- GList *guid_list, *n;
- const char *str;
- GUID *guid;
- gboolean decode;
- QofQueryPredData *pred;
- QofGuidMatch sm;
- xmlNodePtr xp;
- xmlNodePtr node;
- guid_list = NULL;
-
- sm = QOF_GUID_MATCH_ANY;
- xp = root->xmlChildrenNode;
- for (node=xp; node; node = node->next)
- {
- if (node->type != XML_ELEMENT_NODE) continue;
-
- /* char pred doesn't have GET_HOW */
- GET_MATCH5 (sm, "qofquery:guid-match",
- GUID_MATCH, ANY, NONE, NULL, ALL, LIST_ANY);
-
- if (0 == strcmp ("qofquery:guid", node->name))
- {
- str = GET_TEXT (node);
- guid = guid_malloc ();
- decode = string_to_guid (str, guid);
- if (decode)
- {
- guid_list = g_list_append (guid_list, guid);
- }
- else
- {
- guid_free (guid);
- // XXX error! let someone know!
- }
- }
- }
-
- pred = qof_query_guid_predicate (sm, guid_list);
-
- /* The predicate made a copy of everything, so free our stuff */
- for (n=guid_list; n; n=n->next)
- {
- guid_free (n->data);
- }
- g_list_free (guid_list);
- return pred;
-}
-
-/* =============================================================== */
-
-static QofQueryPredData *
-qof_query_pred_char_from_xml (xmlNodePtr root)
-{
- QofQueryPredData *pred;
- QofCharMatch sm;
- const char * char_list;
- xmlNodePtr xp;
- xmlNodePtr node;
-
- char_list = NULL;
- xp = root->xmlChildrenNode;
- sm = QOF_CHAR_MATCH_ANY;
-
- for (node=xp; node; node = node->next)
- {
- if (node->type != XML_ELEMENT_NODE) continue;
-
- /* char pred doesn't have GET_HOW */
- GET_MATCH2 (sm, "qofquery:char-match",
- CHAR_MATCH, ANY, NONE);
- GET_STR (0, char_list=, "qofquery:char-list");
- {}
- }
-
- pred = qof_query_char_predicate (sm, char_list);
- return pred;
-}
-
-/* =============================================================== */
-
-static QofQueryPredData *
-qof_query_pred_numeric_from_xml (xmlNodePtr root)
-{
- QofQueryPredData *pred;
- xmlNodePtr node;
- QofQueryCompare how;
- QofNumericMatch sm;
- gnc_numeric num;
- xmlNodePtr xp;
-
- xp = root->xmlChildrenNode;
- how = QOF_COMPARE_EQUAL;
- sm = QOF_NUMERIC_MATCH_ANY;
-
- for (node=xp; node; node = node->next)
- {
- if (node->type != XML_ELEMENT_NODE) continue;
-
- GET_HOW (how, "qofquery:compare", LT, LTE, EQUAL, GT, GTE, NEQ);
- GET_MATCH3 (sm, "qofquery:numeric-match",
- NUMERIC_MATCH, DEBIT, CREDIT, ANY);
- GET_NUMERIC (0, num=, "qofquery:numeric");
- {}
- }
-
- pred = qof_query_numeric_predicate (how, sm, num);
- return pred;
-}
-
-/* =============================================================== */
-
-static QofQueryPredData *
-qof_query_pred_date_from_xml (xmlNodePtr root)
-{
- xmlNodePtr xp;
- xmlNodePtr node;
- QofQueryCompare how;
- QofDateMatch sm;
- Timespec date;
- QofQueryPredData *pred;
-
- xp = root->xmlChildrenNode;
-
- how = QOF_COMPARE_EQUAL;
- sm = QOF_DATE_MATCH_DAY;
- date = (Timespec){0,0};
-
- for (node=xp; node; node = node->next)
- {
- if (node->type != XML_ELEMENT_NODE) continue;
-
- GET_HOW (how, "qofquery:compare", LT, LTE, EQUAL, GT, GTE, NEQ);
- GET_MATCH2 (sm, "qofquery:date-match",
- DATE_MATCH, NORMAL, DAY);
- GET_DATE (0, date=, "qofquery:date");
- {}
- }
-
- pred = qof_query_date_predicate (how, sm, date);
- return pred;
-}
-
-/* =============================================================== */
-
-static QofQueryPredData *
-qof_query_pred_string_from_xml (xmlNodePtr root)
-{
- QofQueryPredData *pred;
- xmlNodePtr xp;
- xmlNodePtr node;
- QofQueryCompare how;
- QofStringMatch sm;
- gboolean is_regex;
- const char *pstr;
-
- xp = root->xmlChildrenNode;
- how = QOF_COMPARE_EQUAL;
- sm = QOF_STRING_MATCH_CASEINSENSITIVE;
- is_regex = FALSE;
- pstr = NULL;
-
- for (node=xp; node; node = node->next)
- {
- if (node->type != XML_ELEMENT_NODE) continue;
-
- GET_HOW (how, "qofquery:compare", LT, LTE, EQUAL, GT, GTE, NEQ);
- GET_BOOL (0, is_regex=, "qofquery:is-regex");
- GET_STR (0, pstr=, "qofquery:string");
- GET_MATCH2 (sm, "qofquery:string-match",
- STRING_MATCH, NORMAL, CASEINSENSITIVE);
- {}
- }
- pred = qof_query_string_predicate (how, pstr, sm , is_regex);
- return pred;
-}
-
-/* =============================================================== */
-
-static GSList *
-qof_query_param_path_from_xml (xmlNodePtr root)
-{
- xmlNodePtr pterms;
- GSList *plist;
- xmlNodePtr node;
-
- pterms = root->xmlChildrenNode;
- plist = NULL;
- for (node=pterms; node; node = node->next)
- {
- if (node->type != XML_ELEMENT_NODE) continue;
-
- if (0 == strcmp (node->name, "qofquery:param"))
- {
- const char *str = GET_TEXT (node);
- /* BUG? I can't find the matching cache removal. */
- plist = g_slist_append (plist, CACHE_INSERT(str));
- }
- }
- return plist;
-}
-
-/* =============================================================== */
-
-static void
-qof_query_term_from_xml (QofQuery *q, xmlNodePtr root)
-{
- xmlNodePtr node;
- xmlNodePtr term;
- QofQueryPredData *pred;
- GSList *path;
- QofQuery *qt;
- QofQuery *qinv;
-
- pred = NULL;
- path = NULL;
- term = root->xmlChildrenNode;
- for (node=term; node; node = node->next)
- {
- if (node->type != XML_ELEMENT_NODE) continue;
- if (0 == strcmp (node->name, "qofquery:invert"))
- {
- qt = qof_query_create();
- qof_query_term_from_xml (qt, node);
- qinv = qof_query_invert (qt);
- qof_query_merge_in_place (q, qinv, QOF_QUERY_AND);
- qof_query_destroy (qinv);
- qof_query_destroy (qt);
- return;
- }
- else
- if (0 == strcmp (node->name, "qofquery:param-path"))
- {
- path = qof_query_param_path_from_xml (node);
- }
- else
- if (0 == strcmp (node->name, "qofquery:pred-string"))
- {
- pred = qof_query_pred_string_from_xml (node);
- }
- else
- if (0 == strcmp (node->name, "qofquery:pred-date"))
- {
- pred = qof_query_pred_date_from_xml (node);
- }
- else
- if (0 == strcmp (node->name, "qofquery:pred-numeric"))
- {
- pred = qof_query_pred_numeric_from_xml (node);
- }
- else
- if (0 == strcmp (node->name, "qofquery:pred-int32"))
- {
- pred = qof_query_pred_int32_from_xml (node);
- }
- else
- if (0 == strcmp (node->name, "qofquery:pred-int64"))
- {
- pred = qof_query_pred_int64_from_xml (node);
- }
- else
- if (0 == strcmp (node->name, "qofquery:pred-double"))
- {
- pred = qof_query_pred_double_from_xml (node);
- }
- else
- if (0 == strcmp (node->name, "qofquery:pred-boolean"))
- {
- pred = qof_query_pred_boolean_from_xml (node);
- }
- else
- if (0 == strcmp (node->name, "qofquery:pred-char"))
- {
- pred = qof_query_pred_char_from_xml (node);
- }
- else
- if (0 == strcmp (node->name, "qofquery:pred-guid"))
- {
- pred = qof_query_pred_guid_from_xml (node);
- }
- else
- if (0 == strcmp (node->name, "qofquery:pred-kvp"))
- {
- pred = qof_query_pred_kvp_from_xml (node);
- }
- else
- {
- // warning unhandled predicate type
- }
- }
-
- /* At this level, the terms should always be anded */
- qof_query_add_term (q, path, pred, QOF_QUERY_AND);
-}
-
-/* =============================================================== */
-
-static void
-qof_query_and_terms_from_xml (QofQuery *q, xmlNodePtr root)
-{
- xmlNodePtr andterms;
- xmlNodePtr node;
-
- andterms = root->xmlChildrenNode;
- for (node=andterms; node; node = node->next)
- {
- if (node->type != XML_ELEMENT_NODE) continue;
-
- if (0 == strcmp (node->name, "qofquery:term"))
- {
- qof_query_term_from_xml (q, node);
- }
- }
-}
-
-/* =============================================================== */
-
-static void
-qof_query_or_terms_from_xml (QofQuery *q, xmlNodePtr root)
-{
- xmlNodePtr andterms;
- xmlNodePtr node;
- QofQuery *qand;
-
- andterms = root->xmlChildrenNode;
- for (node=andterms; node; node = node->next)
- {
- if (node->type != XML_ELEMENT_NODE) continue;
-
- if (0 == strcmp (node->name, "qofquery:and-terms"))
- {
- qand = qof_query_create ();
- qof_query_and_terms_from_xml (qand, node);
- qof_query_merge_in_place (q, qand, QOF_QUERY_OR);
- qof_query_destroy (qand);
- }
- }
-}
-
-/* =============================================================== */
-
-QofQuery *
-qof_query_from_xml (xmlNodePtr root)
-{
- QofQuery *q;
- xmlChar *version;
- xmlNodePtr qpart;
- xmlNodePtr node;
-
- if (!root) return NULL;
-
- version = xmlGetProp(root, "version");
- if (!root->name || strcmp ("qof:qofquery", root->name))
- {
- // XXX something is wrong. warn ...
- return NULL;
- }
-
- q = qof_query_create ();
-
- qpart = root->xmlChildrenNode;
- for (node=qpart; node; node = node->next)
- {
- if (node->type != XML_ELEMENT_NODE) continue;
-
- GET_STR (q, qof_query_search_for, "qofquery:search-for");
- GET_INT32 (q, qof_query_set_max_results, "qofquery:max-results");
- if (0 == strcmp (node->name, "qofquery:or-terms"))
- {
- qof_query_or_terms_from_xml (q, node);
- }
- else
- if (0 == strcmp (node->name, "qofquery:sort-list"))
- {
-// XXX unfinished I'm bored
- }
- else
- {
- // XXX unknown node type tell someone about it
- }
- }
-
- return q;
-}
-
-/* =============================================================== */
-
-#ifdef UNIT_TEST
-
-#include <stdio.h>
-#include <qof/qofsql.h>
-
-int main (int argc, char * argv[])
-{
- QofQuery *q, *qnew;
- QofSqlQuery *sq;
- xmlNodePtr topnode;
-
- guid_init();
- qof_query_init();
- qof_object_initialize ();
-
- static QofParam params[] = {
- { "adate", QOF_TYPE_DATE, NULL, NULL},
- { "aint", QOF_TYPE_INT32, NULL, NULL},
- { "aint64", QOF_TYPE_INT64, NULL, NULL},
- { "aflt", QOF_TYPE_DOUBLE, NULL, NULL},
- { "abool", QOF_TYPE_BOOLEAN, NULL, NULL},
- { "astr", QOF_TYPE_STRING, NULL, NULL},
- { "adate", QOF_TYPE_DATE, NULL, NULL},
- { "anum", QOF_TYPE_NUMERIC, NULL, NULL},
- { "achar", QOF_TYPE_CHAR, NULL, NULL},
- { "aguid", QOF_TYPE_GUID, NULL, NULL},
- { "akvp", QOF_TYPE_KVP, NULL, NULL},
- { NULL },
- };
-
- qof_class_register ("GncABC", NULL, params);
- sq = qof_sql_query_new();
-
- qof_sql_query_parse (sq,
- "SELECT * from GncABC WHERE aint = 123 "
- "and not aint64 = 6123123456789 "
- "or abool = TRUE "
- "and not aflt >= \'3.14159265358979\' "
- "and not astr=\'asdf\' "
- "and adate<\'01-01-01\' "
- "or anum<\'12301/100\' "
- "or achar != asdf "
- "and aguid != abcdef01234567890fedcba987654321 "
- "and akvp != \'/some/path:abcdef01234567890fedcba987654321\' "
- "and not akvp != \'/some/path/glop:1234\' "
- "and akvp = \'/arf/arf/arf:10.234\' "
- "and akvp != \'/some/other/path:qwerty1234uiop\' "
- "and not akvp = \'/some/final/path:123401/100\' "
- );
- // qof_sql_query_parse (sq, "SELECT * from GncABC;");
- q = qof_sql_query_get_query (sq);
-
- qof_query_print (q);
-
- xmlNodePtr topnode = qof_query_to_xml (q);
-
- qnew = qof_query_from_xml (topnode);
- printf (" ------------------------------------------------------- \n");
- qof_query_print (qnew);
-
- /* If the before and after trees are the same, the test pases. */
- gboolean eq = qof_query_equal (q, qnew);
- printf ("Are the two equal? answer=%d\n", eq);
-
-#define DOPRINT 1
-#ifdef DOPRINT
- xmlDocPtr doc = doc = xmlNewDoc("1.0");
- xmlDocSetRootElement(doc,topnode);
-
- xmlChar *xbuf;
- int bufsz;
- xmlDocDumpFormatMemory (doc, &xbuf, &bufsz, 1);
-
- printf ("%s\n", xbuf);
- xmlFree (xbuf);
- xmlFreeDoc(doc);
-#endif
-
- return 0;
-}
-
-#endif /* UNIT_TEST */
-
-/* ======================== END OF FILE =================== */
Deleted: gnucash/trunk/src/engine/qofquery-deserial.h
===================================================================
--- gnucash/trunk/src/engine/qofquery-deserial.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofquery-deserial.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,47 +0,0 @@
-/********************************************************************\
- * qofquery-deserial.h -- Convert Qof-Query XML to QofQuery *
- * Copyright (C) 2004 Linas Vepstas <linas at linas.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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-/*
- qofquery-deserial.h
- Convert Qof-Query XML to QofQuery
-author Copyright (C) 2004 Linas Vepstas <linas at linas.org>
-*/
-
-#ifndef QOF_QUERY_DESERIAL_H
-#define QOF_QUERY_DESERIAL_H
-
-#include "qofquery.h"
-#include <libxml/tree.h>
-
-/*
- Qof Queries can be converted to and from XML so that they
- can be sent from here to there. This file implements the
- routine needed to convert the XML back into a C struct.
-
- Unfinished. XXX Why is this easier than reading a text/sql
- file?
-
- */
-/* Given an XML tree, reconstruct and return the equivalent query. */
-QofQuery *qof_query_from_xml (xmlNodePtr);
-
-#endif /* QOF_QUERY_DESERIAL_H */
Deleted: gnucash/trunk/src/engine/qofquery-p.h
===================================================================
--- gnucash/trunk/src/engine/qofquery-p.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofquery-p.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,65 +0,0 @@
-/********************************************************************\
- * qofquery-p.h -- internal/private API for finding objects *
- * Copyright (C) 2002 Derek Atkins <warlord at MIT.EDU> *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-#ifndef QOF_QUERY_P_H
-#define QOF_QUERY_P_H
-
-#include "qofquery.h"
-
-typedef struct _QofQueryTerm QofQueryTerm;
-typedef struct _QofQuerySort QofQuerySort;
-
-/* Functions to get Query information */
-int qof_query_get_max_results (QofQuery *q);
-
-
-/* Functions to get and look at QueryTerms */
-
-/* This returns a List of List of Query Terms. Each list of Query
- * Terms are ANDed together, and each list of ANDed terms are ORed
- * together. So, what is returned is the 'or' list of 'and' lists
- * of query term objects.
- *
- * Note that you should NOT modify this list in any way. It belongs
- * to the query.
- */
-GList * qof_query_get_terms (QofQuery *q);
-
-GSList * qof_query_term_get_param_path (QofQueryTerm *queryterm);
-QofQueryPredData *qof_query_term_get_pred_data (QofQueryTerm *queryterm);
-gboolean qof_query_term_is_inverted (QofQueryTerm *queryterm);
-
-
-/* Functions to get and look at QuerySorts */
-
-/* This function returns the primary, secondary, and tertiary sorts.
- * These are part of the query and should NOT be changed!
- */
-void qof_query_get_sorts (QofQuery *q, QofQuerySort **primary,
- QofQuerySort **secondary, QofQuerySort **tertiary);
-
-GSList * qof_query_sort_get_param_path (QofQuerySort *querysort);
-gint qof_query_sort_get_sort_options (QofQuerySort *querysort);
-gboolean qof_query_sort_get_increasing (QofQuerySort *querysort);
-
-#endif /* QOF_QUERY_P_H */
Deleted: gnucash/trunk/src/engine/qofquery-serialize.c
===================================================================
--- gnucash/trunk/src/engine/qofquery-serialize.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofquery-serialize.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,597 +0,0 @@
-/********************************************************************\
- * qofquery-serialize.c -- Convert QofQuery to XML *
- * Copyright (C) 2001,2002,2004 Linas Vepstas <linas at linas.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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-#include "config.h"
-
-#include "qofquery-serialize.h"
-#include "qofquery-p.h"
-#include "qofquerycore-p.h"
-#include "kvp_frame.h"
-
-/* ======================================================= */
-
-#define PUT_STR(TOK,VAL) { \
- xmlNodePtr node; \
- const char * str = (VAL); \
- if (str && 0 != str[0]) \
- { \
- node = xmlNewNode (NULL, TOK); \
- xmlNodeAddContent(node, str); \
- xmlAddChild (topnode, node); \
- } \
-}
-
-#define PUT_INT32(TOK,VAL) { \
- xmlNodePtr node; \
- char buff[80]; \
- g_snprintf (buff, sizeof(buff), "%d", (VAL)); \
- node = xmlNewNode (NULL, TOK); \
- xmlNodeAddContent(node, buff); \
- xmlAddChild (topnode, node); \
-}
-
-#define PUT_INT64(TOK,VAL) { \
- xmlNodePtr node; \
- char buff[80]; \
- g_snprintf (buff, sizeof(buff), "%" G_GINT64_FORMAT, (VAL)); \
- node = xmlNewNode (NULL, TOK); \
- xmlNodeAddContent(node, buff); \
- xmlAddChild (topnode, node); \
-}
-
-#define PUT_DBL(TOK,VAL) { \
- xmlNodePtr node; \
- char buff[80]; \
- g_snprintf (buff, sizeof(buff), "%.18g", (VAL)); \
- node = xmlNewNode (NULL, TOK); \
- xmlNodeAddContent(node, buff); \
- xmlAddChild (topnode, node); \
-}
-
-#define PUT_GUID(TOK,VAL) { \
- xmlNodePtr node; \
- char buff[80]; \
- guid_to_string_buff ((VAL), buff); \
- node = xmlNewNode (NULL, TOK); \
- xmlNodeAddContent(node, buff); \
- xmlAddChild (topnode, node); \
-}
-
-#define PUT_DATE(TOK,VAL) { \
- xmlNodePtr node; \
- char buff[80]; \
- gnc_timespec_to_iso8601_buff ((VAL), buff); \
- node = xmlNewNode (NULL, TOK); \
- xmlNodeAddContent(node, buff); \
- xmlAddChild (topnode, node); \
-}
-
-#define PUT_NUMERIC(TOK,VAL) { \
- xmlNodePtr node; \
- char *str; \
- str = gnc_numeric_to_string (VAL); \
- node = xmlNewNode (NULL, TOK); \
- xmlNodeAddContent(node, str); \
- g_free (str); \
- xmlAddChild (topnode, node); \
-}
-
-#define PUT_BOOL(TOK,VAL) { \
- xmlNodePtr node; \
- gboolean boll = (VAL); \
- node = xmlNewNode (NULL, TOK); \
- if (boll) { \
- xmlNodeAddContent(node, "T"); \
- } else { \
- xmlNodeAddContent(node, "F"); \
- } \
- xmlAddChild (topnode, node); \
-}
-
-#define PUT_HOW(TOK,VAL,A,B,C,D,E,F) { \
- xmlNodePtr node; \
- const char * str = "EQUAL"; \
- switch (VAL) \
- { \
- case QOF_COMPARE_##A: str = #A; break; \
- case QOF_COMPARE_##B: str = #B; break; \
- case QOF_COMPARE_##C: str = #C; break; \
- case QOF_COMPARE_##D: str = #D; break; \
- case QOF_COMPARE_##E: str = #E; break; \
- case QOF_COMPARE_##F: str = #F; break; \
- } \
- node = xmlNewNode (NULL, TOK); \
- xmlNodeAddContent(node, str); \
- xmlAddChild (topnode, node); \
-}
-
-#define PUT_MATCH2(TOK,VAL,PFX,A,B) { \
- xmlNodePtr node; \
- const char * str = #A; \
- switch (VAL) \
- { \
- case QOF_##PFX##_##A: str = #A; break; \
- case QOF_##PFX##_##B: str = #B; break; \
- } \
- node = xmlNewNode (NULL, TOK); \
- xmlNodeAddContent(node, str); \
- xmlAddChild (topnode, node); \
-}
-
-#define PUT_MATCH3(TOK,VAL,PFX,A,B,C) { \
- xmlNodePtr node; \
- const char * str = #A; \
- switch (VAL) \
- { \
- case QOF_##PFX##_##A: str = #A; break; \
- case QOF_##PFX##_##B: str = #B; break; \
- case QOF_##PFX##_##C: str = #C; break; \
- } \
- node = xmlNewNode (NULL, TOK); \
- xmlNodeAddContent(node, str); \
- xmlAddChild (topnode, node); \
-}
-
-#define PUT_MATCH5(TOK,VAL,PFX,A,B,C,D,E) { \
- xmlNodePtr node; \
- const char * str = #A; \
- switch (VAL) \
- { \
- case QOF_##PFX##_##A: str = #A; break; \
- case QOF_##PFX##_##B: str = #B; break; \
- case QOF_##PFX##_##C: str = #C; break; \
- case QOF_##PFX##_##D: str = #D; break; \
- case QOF_##PFX##_##E: str = #E; break; \
- } \
- node = xmlNewNode (NULL, TOK); \
- xmlNodeAddContent(node, str); \
- xmlAddChild (topnode, node); \
-}
-
-/* ======================================================= */
-
-static void
-qof_kvp_value_to_xml (KvpValue *kval, xmlNodePtr topnode)
-{
- KvpValueType kvt = kvp_value_get_type (kval);
-
- switch (kvt)
- {
- case KVP_TYPE_GINT64:
- PUT_INT64 ("qofquery:int64", kvp_value_get_gint64(kval));
- break;
- case KVP_TYPE_DOUBLE:
- PUT_DBL ("qofquery:double", kvp_value_get_double(kval));
- break;
- case KVP_TYPE_NUMERIC:
- PUT_NUMERIC ("qofquery:numeric", kvp_value_get_numeric(kval));
- break;
- case KVP_TYPE_GUID:
- PUT_GUID ("qofquery:guid", kvp_value_get_guid(kval));
- break;
- case KVP_TYPE_STRING:
- PUT_STR ("qofquery:string", kvp_value_get_string(kval));
- break;
- case KVP_TYPE_TIMESPEC:
- PUT_DATE ("qofquery:date", kvp_value_get_timespec(kval));
- break;
- case KVP_TYPE_BINARY:
- case KVP_TYPE_GLIST:
- case KVP_TYPE_FRAME:
- // XXX don't know how to support these.
- break;
- }
-}
-
-/* ======================================================= */
-
-static xmlNodePtr
-qof_query_pred_data_to_xml (QofQueryPredData *pd)
-{
- GList *n;
- GSList *ns;
- xmlNodePtr topnode;
- query_guid_t pdata_g;
- query_string_t pdata_s;
- query_numeric_t pdata_n;
- query_kvp_t pdata_k;
- query_date_t pdata_d;
- query_int64_t pdata_i64;
- query_int32_t pdata_i32;
- query_double_t pdata_db;
- query_boolean_t pdata_bool;
- query_char_t pdata_c;
-
- if (!safe_strcmp (pd->type_name, QOF_TYPE_GUID))
- {
- topnode = xmlNewNode (NULL, "qofquery:pred-guid");
- /* GUID Predicate doesn't do a PUT_HOW */
-
- pdata_g = (query_guid_t) pd;
- PUT_MATCH5("qofquery:guid-match", pdata_g->options,
- GUID_MATCH, ANY, ALL, NONE, NULL, LIST_ANY);
-
- for (n = pdata_g->guids; n; n = n->next)
- {
- PUT_GUID ("qofquery:guid", n->data);
- }
- return topnode;
- }
- if (!safe_strcmp (pd->type_name, QOF_TYPE_STRING))
- {
- topnode = xmlNewNode (NULL, "qofquery:pred-string");
- PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE, NEQ);
-
- pdata_s = (query_string_t) pd;
- PUT_MATCH2("qofquery:string-match", pdata_s->options,
- STRING_MATCH, NORMAL, CASEINSENSITIVE);
- PUT_BOOL ("qofquery:is-regex", pdata_s->is_regex);
- PUT_STR ("qofquery:string", pdata_s->matchstring);
- return topnode;
- }
- if (!safe_strcmp (pd->type_name, QOF_TYPE_NUMERIC))
- {
- topnode = xmlNewNode (NULL, "qofquery:pred-numeric");
- PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE, NEQ);
-
- pdata_n = (query_numeric_t) pd;
- PUT_MATCH3("qofquery:numeric-match", pdata_n->options,
- NUMERIC_MATCH, DEBIT, CREDIT, ANY);
-
- PUT_NUMERIC ("qofquery:numeric", pdata_n->amount);
- return topnode;
- }
- if (!safe_strcmp (pd->type_name, QOF_TYPE_KVP))
- {
- topnode = xmlNewNode (NULL, "qofquery:pred-kvp");
- PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE, NEQ);
-
- pdata_k = (query_kvp_t) pd;
- for (ns=pdata_k->path; ns; ns=ns->next)
- {
- PUT_STR ("qofquery:kvp-path", ns->data);
- }
- qof_kvp_value_to_xml (pdata_k->value, topnode);
- return topnode;
- }
- if (!safe_strcmp (pd->type_name, QOF_TYPE_DATE))
- {
- topnode = xmlNewNode (NULL, "qofquery:pred-date");
- PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE, NEQ);
-
- pdata_d = (query_date_t) pd;
-
- PUT_MATCH2("qofquery:date-match", pdata_d->options,
- DATE_MATCH, NORMAL, DAY);
-
- PUT_DATE ("qofquery:date", pdata_d->date);
- return topnode;
- }
- if (!safe_strcmp (pd->type_name, QOF_TYPE_INT64))
- {
- topnode = xmlNewNode (NULL, "qofquery:pred-int64");
- PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE, NEQ);
-
- pdata_i64 = (query_int64_t) pd;
- PUT_INT64 ("qofquery:int64", pdata_i64->val);
- return topnode;
- }
- if (!safe_strcmp (pd->type_name, QOF_TYPE_INT32))
- {
- topnode = xmlNewNode (NULL, "qofquery:pred-int32");
- PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE, NEQ);
-
- pdata_i32 = (query_int32_t) pd;
-
- PUT_INT32 ("qofquery:int32", pdata_i32->val);
- return topnode;
- }
- if (!safe_strcmp (pd->type_name, QOF_TYPE_DOUBLE))
- {
- topnode = xmlNewNode (NULL, "qofquery:pred-double");
- PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE, NEQ);
-
- pdata_db = (query_double_t) pd;
-
- PUT_DBL ("qofquery:double", pdata_db->val);
- return topnode;
- }
- if (!safe_strcmp (pd->type_name, QOF_TYPE_BOOLEAN))
- {
- topnode = xmlNewNode (NULL, "qofquery:pred-boolean");
- PUT_HOW ("qofquery:compare", pd->how, LT, LTE, EQUAL, GT, GTE, NEQ);
-
- pdata_bool = (query_boolean_t) pd;
-
- PUT_BOOL ("qofquery:boolean", pdata_bool->val);
- return topnode;
- }
- if (!safe_strcmp (pd->type_name, QOF_TYPE_CHAR))
- {
- topnode = xmlNewNode (NULL, "qofquery:pred-char");
- /* There is no PUT_HOW for char-match */
- pdata_c = (query_char_t) pd;
-
- PUT_MATCH2("qofquery:char-match", pdata_c->options,
- CHAR_MATCH, ANY, NONE);
-
- PUT_STR ("qofquery:char-list", pdata_c->char_list);
- return topnode;
- }
- return NULL;
-}
-
-/* ======================================================= */
-
-static xmlNodePtr
-qof_query_param_path_to_xml (GSList *param_path)
-{
- xmlNodePtr topnode;
- GSList *n;
- QofIdTypeConst path;
-
- n = param_path;
- topnode = xmlNewNode (NULL, "qofquery:param-path");
- for ( ; n; n=n->next)
- {
- path = n->data;
- if (!path) continue;
- PUT_STR ("qofquery:param", path);
- }
- return topnode;
-}
-
-/* ======================================================= */
-
-static xmlNodePtr
-qof_query_one_term_to_xml (QofQueryTerm *qt)
-{
- xmlNodePtr node;
- xmlNodePtr term;
- xmlNodePtr topnode;
- gboolean invert;
- GSList *path;
- QofQueryPredData *pd;
-
- invert = qof_query_term_is_inverted (qt);
- term = xmlNewNode (NULL, "qofquery:term");
- topnode = term;
- path = qof_query_term_get_param_path (qt);
- pd = qof_query_term_get_pred_data (qt);
- if (invert)
- {
- /* inverter becomes new top mode */
- topnode = xmlNewNode (NULL, "qofquery:invert");
- xmlAddChild (term, topnode);
- }
-
- node = qof_query_param_path_to_xml (path);
- if (node) xmlAddChild (topnode, node);
-
- node = qof_query_pred_data_to_xml (pd);
- if (node) xmlAddChild (topnode, node);
-
- return term;
-}
-
-/* ======================================================= */
-
-static xmlNodePtr
-qof_query_and_terms_to_xml (GList *and_terms)
-{
- xmlNodePtr terms;
- GList *n;
- QofQueryTerm *qt;
- xmlNodePtr t;
-
- terms = xmlNewNode (NULL, "qofquery:and-terms");
- n = and_terms;
- for ( ; n; n=n->next)
- {
- qt = n->data;
- if (!qt) continue;
-
- t = qof_query_one_term_to_xml (n->data);
- if (t) xmlAddChild (terms, t);
- }
- return terms;
-}
-
-/* ======================================================= */
-
-static xmlNodePtr
-qof_query_terms_to_xml (QofQuery *q)
-{
- xmlNodePtr terms;
- GList *n;
- xmlNodePtr andt;
-
- terms = NULL;
- n = qof_query_get_terms (q);
- if (!n) return NULL;
- terms = xmlNewNode (NULL, "qofquery:or-terms");
-
- for ( ; n; n=n->next)
- {
- andt = qof_query_and_terms_to_xml (n->data);
- if (andt) xmlAddChild (terms, andt);
- }
- return terms;
-}
-
-/* ======================================================= */
-
-static xmlNodePtr
-qof_query_sorts_to_xml (QofQuery *q)
-{
- QofQuerySort *s[3];
- xmlNodePtr sortlist;
- GSList *plist;
- xmlNodePtr sort;
- xmlNodePtr topnode;
- gboolean increasing;
- gint opt;
- xmlNodePtr pl;
- int i;
-
- qof_query_get_sorts (q, &s[0], &s[1], &s[2]);
-
- if (NULL == s[0]) return NULL;
-
- sortlist = xmlNewNode (NULL, "qofquery:sort-list");
- for (i=0; i<3; i++)
- {
- if (NULL == s[i]) continue;
-
- plist = qof_query_sort_get_param_path (s[i]);
- if (!plist) continue;
-
- sort = xmlNewNode (NULL, "qofquery:sort");
- xmlAddChild (sortlist, sort);
-
- topnode = sort;
-
- increasing = qof_query_sort_get_increasing (s[i]);
- PUT_STR ("qofquery:order", increasing ? "DESCENDING" : "ASCENDING");
-
- opt = qof_query_sort_get_sort_options (s[i]);
- PUT_INT32 ("qofquery:options", opt);
-
- pl = qof_query_param_path_to_xml (plist);
- if (pl) xmlAddChild (sort, pl);
- }
-
- return sortlist;
-}
-
-/* ======================================================= */
-
-static void
-do_qof_query_to_xml (QofQuery *q, xmlNodePtr topnode)
-{
- QofIdType search_for;
- xmlNodePtr terms;
- xmlNodePtr sorts;
- gint max_results;
-
- search_for = qof_query_get_search_for (q);
- PUT_STR ("qofquery:search-for", search_for);
-
- terms = qof_query_terms_to_xml(q);
- if (terms) xmlAddChild (topnode, terms);
-
- sorts = qof_query_sorts_to_xml (q);
- if (sorts) xmlAddChild (topnode, sorts);
-
- max_results = qof_query_get_max_results (q);
- PUT_INT32 ("qofquery:max-results", max_results);
-}
-
-/* ======================================================= */
-
-xmlNodePtr
-qof_query_to_xml (QofQuery *q)
-{
- xmlNodePtr topnode;
- xmlNodePtr node;
- xmlNsPtr ns;
-
- topnode = xmlNewNode(NULL, "qof:qofquery");
- xmlSetProp(topnode, "version", "1.0.1");
-
- // XXX path to DTD is wrong
- // ns = xmlNewNs (topnode, "file:" "/usr/share/lib" "/qofquery.dtd", "qof");
-
- do_qof_query_to_xml (q, topnode);
-
- return topnode;
-}
-
-/* =============================================================== */
-
-#ifdef UNIT_TEST
-
-#include <stdio.h>
-#include <qof/qofsql.h>
-
-int main (int argc, char * argv[])
-{
- QofQuery *q;
- QofSqlQuery *sq;
- xmlDocPtr doc;
- xmlNodePtr topnode;
- xmlChar *xbuf;
- int bufsz;
- xmlOutputBufferPtr xbuf;
-
- qof_query_init();
- qof_object_initialize ();
-
- static QofParam params[] = {
- { "adate", QOF_TYPE_DATE, NULL, NULL},
- { "aint", QOF_TYPE_INT32, NULL, NULL},
- { "aint64", QOF_TYPE_INT64, NULL, NULL},
- { "astr", QOF_TYPE_STRING, NULL, NULL},
- { NULL },
- };
-
- qof_class_register ("GncABC", NULL, params);
- sq = qof_sql_query_new();
-
- qof_sql_query_parse (sq,
- "SELECT * from GncABC WHERE aint = 123 "
- "or not astr=\'asdf\' "
- "and aint64 = 9876123456789;");
- // qof_sql_query_parse (sq, "SELECT * from GncABC;");
- q = qof_sql_query_get_query (sq);
-
- qof_query_print (q);
-
- doc = doc = xmlNewDoc("1.0");
- topnode = qof_query_to_xml (q);
- xmlDocSetRootElement(doc,topnode);
-
- xmlDocDumpFormatMemory (doc, &xbuf, &bufsz, 1);
-
- printf ("%s\n", xbuf);
- xmlFree (xbuf);
- xmlFreeDoc(doc);
-
-#if 0
-printf ("duude\n");
- // xmlOutputBufferPtr xbuf = xmlAllocOutputBuffer (enc);
- xbuf = xmlOutputBufferCreateFile (stdout, NULL);
-printf ("duude\n");
-
- xbuf = xmlOutputBufferCreateFd (1, NULL);
-printf ("duude\n");
- xmlNodeDumpOutput (xbuf, NULL, topnode, 99, 99, "iso-8859-1");
- // xmlElemDump (stdout, NULL, topnode);
-#endif
-
- return 0;
-}
-
-#endif /* UNIT_TEST */
-
-/* ======================== END OF FILE =================== */
Deleted: gnucash/trunk/src/engine/qofquery-serialize.h
===================================================================
--- gnucash/trunk/src/engine/qofquery-serialize.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofquery-serialize.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,42 +0,0 @@
-/********************************************************************\
- * qofquery-serialize.h -- Convert QofQuery to XML *
- * Copyright (C) 2004 Linas Vepstas <linas at linas.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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-/* qofquery-serialize.h
- Convert QofQuery to XML
- Copyright (C) 2001,2002,2004 Linas Vepstas <linas at linas.org>
- */
-
-#ifndef QOF_QUERY_SERIALIZE_H
-#define QOF_QUERY_SERIALIZE_H
-
-#include "qofquery.h"
-#include <libxml/tree.h>
-
-/* XML Serialize Queries to/from XML */
-
-/* Take the query passed as input, and serialize it into XML.
- * The DTD used will be a very qofquery specific DTD
- * This is NOT the XQuery XML.
- */
-xmlNodePtr qof_query_to_xml (QofQuery *q);
-
-#endif /* QOF_QUERY_SERIALIZE_H */
Deleted: gnucash/trunk/src/engine/qofquery.c
===================================================================
--- gnucash/trunk/src/engine/qofquery.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofquery.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,1880 +0,0 @@
-/********************************************************************\
- * qof_query.c -- Implement predicate API for searching for objects *
- * Copyright (C) 2002 Derek Atkins <warlord at MIT.EDU> *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-#include "config.h"
-
-#include <sys/types.h>
-#include <time.h>
-#include <glib.h>
-#include <regex.h>
-#include <string.h>
-
-#include "gnc-trace.h"
-#include "gnc-engine-util.h"
-
-#include "qofbackend-p.h"
-#include "qofbook.h"
-#include "qofbook-p.h"
-#include "qofclass.h"
-#include "qofclass-p.h"
-#include "qofobject.h"
-#include "qofquery.h"
-#include "qofquery-p.h"
-#include "qofquerycore.h"
-#include "qofquerycore-p.h"
-
-static QofLogModule log_module = QOF_MOD_QUERY;
-
-struct _QofQueryTerm
-{
- GSList * param_list;
- QofQueryPredData *pdata;
- gboolean invert;
-
- /* These values are filled in during "compilation" of the query
- * term, based upon the obj_name, param_name, and searched-for
- * object type. If conv_fcn is NULL, then we don't know how to
- * convert types.
- */
- GSList * param_fcns;
- QofQueryPredicateFunc pred_fcn;
-};
-
-struct _QofQuerySort
-{
- GSList * param_list;
- gint options;
- gboolean increasing;
-
- /* These values are filled in during "compilation" of the query
- * term, based upon the obj_name, param_name, and searched-for
- * object type. If conv_fcn is NULL, then we don't know how to
- * convert types.
- */
- gboolean use_default;
- GSList * param_fcns; /* Chain of paramters to walk */
- QofSortFunc obj_cmp; /* In case you are comparing objects */
- QofCompareFunc comp_fcn; /* When you are comparing core types */
-};
-
-/* The QUERY structure */
-struct _QofQuery
-{
- /* The object type that we're searching for */
- QofIdType search_for;
-
- /* terms is a list of the OR-terms in a sum-of-products
- * logical expression. */
- GList * terms;
-
- /* sorting and chopping is independent of the search filter */
-
- QofQuerySort primary_sort;
- QofQuerySort secondary_sort;
- QofQuerySort tertiary_sort;
- QofSortFunc defaultSort; /* <- Computed from search_for */
-
- /* The maximum number of results to return */
- int max_results;
-
- /* list of books that will be participating in the query */
- GList * books;
-
- /* a map of book to backend-compiled queries */
- GHashTable* be_compiled;
-
- /* cache the results so we don't have to run the whole search
- * again until it's really necessary */
- int changed;
-
- GList * results;
-};
-
-typedef struct _QofQueryCB
-{
- QofQuery * query;
- GList * list;
- int count;
-} QofQueryCB;
-
-/* initial_term will be owned by the new Query */
-static void query_init (QofQuery *q, QofQueryTerm *initial_term)
-{
- GList * or = NULL;
- GList *and = NULL;
- GHashTable *ht;
-
- if (initial_term) {
- or = g_list_alloc ();
- and = g_list_alloc ();
- and->data = initial_term;
- or->data = and;
- }
-
- if(q->terms)
- qof_query_clear (q);
-
- g_list_free (q->results);
- g_list_free (q->books);
-
- g_slist_free (q->primary_sort.param_list);
- g_slist_free (q->secondary_sort.param_list);
- g_slist_free (q->tertiary_sort.param_list);
-
- g_slist_free (q->primary_sort.param_fcns);
- g_slist_free (q->secondary_sort.param_fcns);
- g_slist_free (q->tertiary_sort.param_fcns);
-
- ht = q->be_compiled;
- memset (q, 0, sizeof (*q));
- q->be_compiled = ht;
-
- q->terms = or;
- q->changed = 1;
- q->max_results = -1;
-
- q->primary_sort.param_list = g_slist_prepend (NULL, QUERY_DEFAULT_SORT);
- q->primary_sort.increasing = TRUE;
- q->secondary_sort.increasing = TRUE;
- q->tertiary_sort.increasing = TRUE;
-}
-
-static void swap_terms (QofQuery *q1, QofQuery *q2)
-{
- GList *g;
-
- if (!q1 || !q2) return;
-
- g = q1->terms;
- q1->terms = q2->terms;
- q2->terms = g;
-
- g = q1->books;
- q1->books = q2->books;
- q2->books = g;
-
- q1->changed = 1;
- q2->changed = 1;
-}
-
-static void free_query_term (QofQueryTerm *qt)
-{
- if (!qt) return;
-
- qof_query_core_predicate_free (qt->pdata);
- g_slist_free (qt->param_list);
- g_slist_free (qt->param_fcns);
- g_free (qt);
-}
-
-static QofQueryTerm * copy_query_term (QofQueryTerm *qt)
-{
- QofQueryTerm *new_qt;
- if (!qt) return NULL;
-
- new_qt = g_new0 (QofQueryTerm, 1);
- memcpy (new_qt, qt, sizeof(QofQueryTerm));
- new_qt->param_list = g_slist_copy (qt->param_list);
- new_qt->param_fcns = g_slist_copy (qt->param_fcns);
- new_qt->pdata = qof_query_core_predicate_copy (qt->pdata);
- return new_qt;
-}
-
-static GList * copy_and_terms (GList *and_terms)
-{
- GList *and = NULL;
- GList *cur_and;
-
- for(cur_and = and_terms; cur_and; cur_and = cur_and->next)
- {
- and = g_list_prepend(and, copy_query_term (cur_and->data));
- }
-
- return g_list_reverse(and);
-}
-
-static GList *
-copy_or_terms(GList * or_terms)
-{
- GList * or = NULL;
- GList * cur_or;
-
- for(cur_or = or_terms; cur_or; cur_or = cur_or->next)
- {
- or = g_list_prepend(or, copy_and_terms(cur_or->data));
- }
-
- return g_list_reverse(or);
-}
-
-static void copy_sort (QofQuerySort *dst, const QofQuerySort *src)
-{
- memcpy (dst, src, sizeof (*dst));
- dst->param_list = g_slist_copy (src->param_list);
- dst->param_fcns = g_slist_copy (src->param_fcns);
-}
-
-static void free_sort (QofQuerySort *s)
-{
- g_slist_free (s->param_list);
- s->param_list = NULL;
-
- g_slist_free (s->param_fcns);
- s->param_fcns = NULL;
-}
-
-static void free_members (QofQuery *q)
-{
- GList * cur_or;
-
- if (q == NULL) return;
-
- for(cur_or = q->terms; cur_or; cur_or = cur_or->next)
- {
- GList * cur_and;
-
- for(cur_and = cur_or->data; cur_and; cur_and = cur_and->next)
- {
- free_query_term(cur_and->data);
- cur_and->data = NULL;
- }
-
- g_list_free(cur_or->data);
- cur_or->data = NULL;
- }
-
- free_sort (&(q->primary_sort));
- free_sort (&(q->secondary_sort));
- free_sort (&(q->tertiary_sort));
-
- g_list_free(q->terms);
- q->terms = NULL;
-
- g_list_free(q->books);
- q->books = NULL;
-
- g_list_free(q->results);
- q->results = NULL;
-}
-
-static int cmp_func (QofQuerySort *sort, QofSortFunc default_sort,
- gconstpointer a, gconstpointer b)
-{
- QofParam *param = NULL;
- GSList *node;
- gpointer conva, convb;
-
- g_return_val_if_fail (sort, 0);
-
- /* See if this is a default sort */
- if (sort->use_default)
- {
- if (default_sort) return default_sort ((gpointer)a, (gpointer)b);
- return 0;
- }
-
- /* If no parameters, consider them equal */
- if (!sort->param_fcns) return 0;
-
- /* no compare function, consider the two objects equal */
- if (!sort->comp_fcn && !sort->obj_cmp) return 0;
-
- /* Do the list of conversions */
- conva = (gpointer)a;
- convb = (gpointer)b;
- for (node = sort->param_fcns; node; node = node->next)
- {
- param = node->data;
-
- /* The last term is really the "parameter getter",
- * unless we're comparing objects ;) */
- if (!node->next && !sort->obj_cmp)
- break;
-
- /* Do the converstions */
- conva = (param->param_getfcn) (conva, param);
- convb = (param->param_getfcn) (convb, param);
- }
-
- /* And now return the (appropriate) compare */
- if (sort->comp_fcn)
- {
- int rc = sort->comp_fcn (conva, convb, sort->options, param);
- return rc;
- }
-
- return sort->obj_cmp (conva, convb);
-}
-
-static QofQuery * sortQuery = NULL;
-
-static int sort_func (gconstpointer a, gconstpointer b)
-{
- int retval;
-
- g_return_val_if_fail (sortQuery, 0);
-
- retval = cmp_func (&(sortQuery->primary_sort), sortQuery->defaultSort, a, b);
- if (retval == 0)
- {
- retval = cmp_func (&(sortQuery->secondary_sort), sortQuery->defaultSort,
- a, b);
- if (retval == 0)
- {
- retval = cmp_func (&(sortQuery->tertiary_sort), sortQuery->defaultSort,
- a, b);
- return sortQuery->tertiary_sort.increasing ? retval : -retval;
- }
- else
- {
- return sortQuery->secondary_sort.increasing ? retval : -retval;
- }
- }
- else
- {
- return sortQuery->primary_sort.increasing ? retval : -retval;
- }
-}
-
-/* ==================================================================== */
-/* This is the main workhorse for performing the query. For each
- * object, it walks over all of the query terms to see if the
- * object passes the seive.
- */
-
-static int
-check_object (QofQuery *q, gpointer object)
-{
- GList * and_ptr;
- GList * or_ptr;
- QofQueryTerm * qt;
- int and_terms_ok=1;
-
- ENTER (" object=%p terms=%p name=%s",
- object, q->terms, qof_object_printable (q->search_for, object));
-
- for(or_ptr = q->terms; or_ptr; or_ptr = or_ptr->next)
- {
- and_terms_ok = 1;
- for(and_ptr = or_ptr->data; and_ptr; and_ptr = and_ptr->next)
- {
- qt = (QofQueryTerm *)(and_ptr->data);
- if (qt->param_fcns && qt->pred_fcn)
- {
- GSList *node;
- QofParam *param = NULL;
- gpointer conv_obj = object;
-
- /* iterate through the conversions */
- for (node = qt->param_fcns; node; node = node->next)
- {
- param = node->data;
-
- /* The last term is the actual parameter getter */
- if (!node->next) break;
-
- conv_obj = param->param_getfcn (conv_obj, param);
- }
-
- if (((qt->pred_fcn)(conv_obj, param, qt->pdata)) == qt->invert)
- {
- and_terms_ok = 0;
- break;
- }
- }
- else
- {
- /* XXX: Don't know how to do this conversion -- do we care? */
- }
- }
- if (and_terms_ok)
- {
- LEAVE (" (terms are OK)");
- return 1;
- }
- }
-
- /* If there are no terms, assume a "match any" applies.
- * A query with no terms is still meaningful, since the user
- * may want to get all objects, but in a particular sorted
- * order.
- */
- LEAVE (" ");
- if (NULL == q->terms) return 1;
- return 0;
-}
-
-/* walk the list of parameters, starting with the given object, and
- * compile the list of parameter get-functions. Save the last valid
- * parameter definition in "final" and return the list of functions.
- *
- * returns NULL if the first parameter is bad (and final is unchanged).
- */
-static GSList *
-compile_params (GSList *param_list, QofIdType start_obj,
- QofParam const **final)
-{
- const QofParam *objDef = NULL;
- GSList *fcns = NULL;
-
- ENTER ("param_list=%p id=%s", param_list, start_obj);
- g_return_val_if_fail (param_list, NULL);
- g_return_val_if_fail (start_obj, NULL);
- g_return_val_if_fail (final, NULL);
-
- for (; param_list; param_list = param_list->next)
- {
- QofIdType param_name = param_list->data;
- objDef = qof_class_get_parameter (start_obj, param_name);
-
- /* If it doesn't exist, then we've reached the end */
- if (!objDef) break;
-
- /* Save off this parameter */
- fcns = g_slist_prepend (fcns, (gpointer) objDef);
-
- /* Save this off, just in case */
- *final = objDef;
-
- /* And reset for the next parameter */
- start_obj = (QofIdType) objDef->param_type;
- }
-
- LEAVE ("fcns=%p", fcns);
- return (g_slist_reverse (fcns));
-}
-
-static void
-compile_sort (QofQuerySort *sort, QofIdType obj)
-{
- const QofParam *resObj = NULL;
-
- ENTER ("sort=%p id=%s params=%p", sort, obj, sort->param_list);
- sort->use_default = FALSE;
-
- g_slist_free (sort->param_fcns);
- sort->param_fcns = NULL;
- sort->comp_fcn = NULL;
- sort->obj_cmp = NULL;
-
- /* An empty param_list implies "no sort" */
- if (!sort->param_list) { LEAVE (" "); return; }
-
- /* Walk the parameter list of obtain the parameter functions */
- sort->param_fcns = compile_params (sort->param_list, obj, &resObj);
-
- /* If we have valid parameters, grab the compare function,
- * If not, check if this is the default sort.
- */
- if (sort->param_fcns)
- {
- sort->comp_fcn = qof_query_core_get_compare (resObj->param_type);
-
- /* Hrm, perhaps this is an object compare, not a core compare? */
- if (sort->comp_fcn == NULL)
- {
- sort->obj_cmp = qof_class_get_default_sort (resObj->param_type);
- }
- }
- else if (!safe_strcmp (sort->param_list->data, QUERY_DEFAULT_SORT))
- {
- sort->use_default = TRUE;
- }
- LEAVE ("sort=%p id=%s", sort, obj);
-}
-
-static void compile_terms (QofQuery *q)
-{
- GList *or_ptr, *and_ptr, *node;
-
- ENTER (" query=%p", q);
- /* Find the specific functions for this Query. Note that the
- * Query's search_for should now be set to the new type.
- */
- for (or_ptr = q->terms; or_ptr; or_ptr = or_ptr->next) {
- for (and_ptr = or_ptr->data; and_ptr; and_ptr = and_ptr->next) {
- QofQueryTerm *qt = and_ptr->data;
- const QofParam *resObj = NULL;
-
- g_slist_free (qt->param_fcns);
- qt->param_fcns = NULL;
-
- /* Walk the parameter list of obtain the parameter functions */
- qt->param_fcns = compile_params (qt->param_list, q->search_for,
- &resObj);
-
- /* If we have valid parameters, grab the predicate function,
- * If not, see if this is the default sort.
- */
-
- if (qt->param_fcns)
- qt->pred_fcn = qof_query_core_get_predicate (resObj->param_type);
- else
- qt->pred_fcn = NULL;
- }
- }
-
- /* Update the sort functions */
- compile_sort (&(q->primary_sort), q->search_for);
- compile_sort (&(q->secondary_sort), q->search_for);
- compile_sort (&(q->tertiary_sort), q->search_for);
-
- q->defaultSort = qof_class_get_default_sort (q->search_for);
-
- /* Now compile the backend instances */
- for (node = q->books; node; node = node->next) {
- QofBook *book = node->data;
- QofBackend *be = book->backend;
-
- if (be && be->compile_query) {
- gpointer result = (be->compile_query)(be, q);
- if (result)
- g_hash_table_insert (q->be_compiled, book, result);
- }
- }
- LEAVE (" query=%p", q);
-}
-
-static void check_item_cb (gpointer object, gpointer user_data)
-{
- QofQueryCB *ql = user_data;
-
- if (!object || !ql) return;
-
- if (check_object (ql->query, object)) {
- ql->list = g_list_prepend (ql->list, object);
- ql->count++;
- }
- return;
-}
-
-static int param_list_cmp (GSList *l1, GSList *l2)
-{
- while (1) {
- int ret;
-
- /* Check the easy stuff */
- if (!l1 && !l2) return 0;
- if (!l1 && l2) return -1;
- if (l1 && !l2) return 1;
-
- ret = safe_strcmp (l1->data, l2->data);
- if (ret)
- return ret;
-
- l1 = l1->next;
- l2 = l2->next;
- }
-}
-
-static GList * merge_books (GList *l1, GList *l2)
-{
- GList *res = NULL;
- GList *node;
-
- res = g_list_copy (l1);
-
- for (node = l2; node; node = node->next) {
- if (g_list_index (res, node->data) == -1)
- res = g_list_prepend (res, node->data);
- }
-
- return res;
-}
-
-static gboolean
-query_free_compiled (gpointer key, gpointer value, gpointer not_used)
-{
- QofBook* book = key;
- QofBackend* be = book->backend;
-
- if (be && be->free_query)
- (be->free_query)(be, value);
-
- return TRUE;
-}
-
-/* clear out any cached query_compilations */
-static void query_clear_compiles (QofQuery *q)
-{
- g_hash_table_foreach_remove (q->be_compiled, query_free_compiled, NULL);
-}
-
-/********************************************************************/
-/* PUBLISHED API FUNCTIONS */
-
-GSList *
-qof_query_build_param_list (char const *param, ...)
-{
- GSList *param_list = NULL;
- char const *this_param;
- va_list ap;
-
- if (!param)
- return NULL;
-
- va_start (ap, param);
-
- for (this_param = param; this_param; this_param = va_arg (ap, const char *))
- param_list = g_slist_prepend (param_list, (gpointer)this_param);
-
- va_end (ap);
-
- return g_slist_reverse (param_list);
-}
-
-void qof_query_add_term (QofQuery *q, GSList *param_list,
- QofQueryPredData *pred_data, QofQueryOp op)
-{
- QofQueryTerm *qt;
- QofQuery *qr, *qs;
-
- if (!q || !param_list || !pred_data) return;
-
- qt = g_new0 (QofQueryTerm, 1);
- qt->param_list = param_list;
- qt->pdata = pred_data;
- qs = qof_query_create ();
- query_init (qs, qt);
-
- if (qof_query_has_terms (q))
- qr = qof_query_merge (q, qs, op);
- else
- qr = qof_query_merge (q, qs, QOF_QUERY_OR);
-
- swap_terms (q, qr);
- qof_query_destroy (qs);
- qof_query_destroy (qr);
-}
-
-void qof_query_purge_terms (QofQuery *q, GSList *param_list)
-{
- QofQueryTerm *qt;
- GList *or, *and;
-
- if (!q || !param_list) return;
-
- for (or = q->terms; or; or = or->next) {
- for (and = or->data; and; and = and->next) {
- qt = and->data;
- if (!param_list_cmp (qt->param_list, param_list)) {
- if (g_list_length (or->data) == 1) {
- q->terms = g_list_remove_link (q->terms, or);
- g_list_free_1 (or);
- or = q->terms;
- break;
- } else {
- or->data = g_list_remove_link (or->data, and);
- g_list_free_1 (and);
- and = or->data;
- if (!and) break;
- }
- q->changed = 1;
- free_query_term (qt);
- }
- }
- if (!or) break;
- }
-}
-
-GList * qof_query_run (QofQuery *q)
-{
- GList *matching_objects = NULL;
- GList *node;
- int object_count = 0;
-
- if (!q) return NULL;
- g_return_val_if_fail (q->search_for, NULL);
- g_return_val_if_fail (q->books, NULL);
- ENTER (" q=%p", q);
-
- /* XXX: Prioritize the query terms? */
-
- /* prepare the Query for processing */
- if (q->changed)
- {
- query_clear_compiles (q);
- compile_terms (q);
- }
-
- /* Maybe log this sucker */
- if (gnc_should_log (log_module, GNC_LOG_DETAIL)) qof_query_print (q);
-
- /* Now run the query over all the objects and save the results */
- {
- QofQueryCB qcb;
-
- memset (&qcb, 0, sizeof (qcb));
- qcb.query = q;
-
- /* For each book */
- for (node=q->books; node; node=node->next)
- {
- QofBook *book = node->data;
- QofBackend *be = book->backend;
-
- /* run the query in the backend */
- if (be)
- {
- gpointer compiled_query = g_hash_table_lookup (q->be_compiled, book);
-
- if (compiled_query && be->run_query)
- {
- (be->run_query) (be, compiled_query);
- }
- }
-
- /* And then iterate over all the objects */
- qof_object_foreach (q->search_for, book, (QofEntityForeachCB) check_item_cb, &qcb);
- }
-
- matching_objects = qcb.list;
- object_count = qcb.count;
- }
- PINFO ("matching objects=%p count=%d", matching_objects, object_count);
-
- /* There is no absolute need to reverse this list, since it's being
- * sorted below. However, in the common case, we will be searching
- * in a confined location where the objects are already in order,
- * thus reversing will put us in the correct order we want and make
- * the sorting go much faster.
- */
- matching_objects = g_list_reverse(matching_objects);
-
- /* Now sort the matching objects based on the search criteria
- * sortQuery is an unforgivable use of static global data...
- * I just can't figure out how else to do this sanely.
- */
- if (q->primary_sort.comp_fcn || q->primary_sort.obj_cmp ||
- (q->primary_sort.use_default && q->defaultSort))
- {
- sortQuery = q;
- matching_objects = g_list_sort(matching_objects, sort_func);
- sortQuery = NULL;
- }
-
- /* Crop the list to limit the number of splits. */
- if((object_count > q->max_results) && (q->max_results > -1))
- {
- if(q->max_results > 0)
- {
- GList *mptr;
-
- /* mptr is set to the first node of what will be the new list */
- mptr = g_list_nth(matching_objects, object_count - q->max_results);
- /* mptr should not be NULL, but let's be safe */
- if (mptr != NULL)
- {
- if (mptr->prev != NULL) mptr->prev->next = NULL;
- mptr->prev = NULL;
- }
- g_list_free(matching_objects);
- matching_objects = mptr;
- }
- else
- {
- /* q->max_results == 0 */
- g_list_free(matching_objects);
- matching_objects = NULL;
- }
- object_count = q->max_results;
- }
-
- q->changed = 0;
-
- g_list_free(q->results);
- q->results = matching_objects;
-
- LEAVE (" q=%p", q);
- return matching_objects;
-}
-
-GList *
-qof_query_last_run (QofQuery *query)
-{
- if (!query)
- return NULL;
-
- return query->results;
-}
-
-void qof_query_clear (QofQuery *query)
-{
- QofQuery *q2 = qof_query_create ();
- swap_terms (query, q2);
- qof_query_destroy (q2);
-
- g_list_free (query->books);
- query->books = NULL;
- g_list_free (query->results);
- query->results = NULL;
- query->changed = 1;
-}
-
-QofQuery * qof_query_create (void)
-{
- QofQuery *qp = g_new0 (QofQuery, 1);
- qp->be_compiled = g_hash_table_new (g_direct_hash, g_direct_equal);
- query_init (qp, NULL);
- return qp;
-}
-
-void qof_query_search_for (QofQuery *q, QofIdTypeConst obj_type)
-{
- if (!q || !obj_type)
- return;
-
- if (safe_strcmp (q->search_for, obj_type)) {
- q->search_for = (QofIdType) obj_type;
- q->changed = 1;
- }
-}
-
-QofQuery * qof_query_create_for (QofIdTypeConst obj_type)
-{
- QofQuery *q;
- if (!obj_type)
- return NULL;
- q = qof_query_create ();
- qof_query_search_for (q, obj_type);
- return q;
-}
-
-int qof_query_has_terms (QofQuery *q)
-{
- if (!q) return 0;
- return g_list_length (q->terms);
-}
-
-int qof_query_num_terms (QofQuery *q)
-{
- GList *o;
- int n = 0;
- if (!q) return 0;
- for (o = q->terms; o; o=o->next)
- n += g_list_length(o->data);
- return n;
-}
-
-gboolean qof_query_has_term_type (QofQuery *q, GSList *term_param)
-{
- GList *or;
- GList *and;
-
- if (!q || !term_param)
- return FALSE;
-
- for(or = q->terms; or; or = or->next) {
- for(and = or->data; and; and = and->next) {
- QofQueryTerm *qt = and->data;
- if (!param_list_cmp (term_param, qt->param_list))
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-GSList * qof_query_get_term_type (QofQuery *q, GSList *term_param)
-{
- GList *or;
- GList *and;
- GSList *results = NULL;
-
- if (!q || !term_param)
- return FALSE;
-
- for(or = q->terms; or; or = or->next) {
- for(and = or->data; and; and = and->next) {
- QofQueryTerm *qt = and->data;
- if (!param_list_cmp (term_param, qt->param_list))
- results = g_slist_append(results, qt->pdata);
- }
- }
-
- return results;
-}
-
-void qof_query_destroy (QofQuery *q)
-{
- if (!q) return;
- free_members (q);
- query_clear_compiles (q);
- g_hash_table_destroy (q->be_compiled);
- g_free (q);
-}
-
-QofQuery * qof_query_copy (QofQuery *q)
-{
- QofQuery *copy;
- GHashTable *ht;
-
- if (!q) return NULL;
- copy = qof_query_create ();
- ht = copy->be_compiled;
- free_members (copy);
-
- memcpy (copy, q, sizeof (QofQuery));
-
- copy->be_compiled = ht;
- copy->terms = copy_or_terms (q->terms);
- copy->books = g_list_copy (q->books);
- copy->results = g_list_copy (q->results);
-
- copy_sort (&(copy->primary_sort), &(q->primary_sort));
- copy_sort (&(copy->secondary_sort), &(q->secondary_sort));
- copy_sort (&(copy->tertiary_sort), &(q->tertiary_sort));
-
- copy->changed = 1;
-
- return copy;
-}
-
-/********************************************************************
- * qof_query_invert
- * return a newly-allocated Query object which is the
- * logical inverse of the original.
- ********************************************************************/
-
-QofQuery * qof_query_invert (QofQuery *q)
-{
- QofQuery * retval;
- QofQuery * right, * left, * iright, * ileft;
- QofQueryTerm * qt;
- GList * aterms;
- GList * cur;
- GList * new_oterm;
- int num_or_terms;
-
- if (!q)
- return NULL;
-
- num_or_terms = g_list_length(q->terms);
-
- switch(num_or_terms)
- {
- case 0:
- retval = qof_query_create();
- retval->max_results = q->max_results;
- break;
-
- /* This is the DeMorgan expansion for a single AND expression. */
- /* !(abc) = !a + !b + !c */
- case 1:
- retval = qof_query_create();
- retval->max_results = q->max_results;
- retval->books = g_list_copy (q->books);
- retval->search_for = q->search_for;
- retval->changed = 1;
-
- aterms = g_list_nth_data(q->terms, 0);
- new_oterm = NULL;
- for(cur=aterms; cur; cur=cur->next) {
- qt = copy_query_term(cur->data);
- qt->invert = !(qt->invert);
- new_oterm = g_list_append(NULL, qt);
-
- /* g_list_append() can take forever, so let's do this for speed
- * in "large" queries.
- */
- retval->terms = g_list_reverse(retval->terms);
- retval->terms = g_list_prepend(retval->terms, new_oterm);
- retval->terms = g_list_reverse(retval->terms);
- }
- break;
-
- /* If there are multiple OR-terms, we just recurse by
- * breaking it down to !(a + b + c) =
- * !a * !(b + c) = !a * !b * !c. */
- default:
- right = qof_query_create();
- right->terms = copy_or_terms(g_list_nth(q->terms, 1));
-
- left = qof_query_create();
- left->terms = g_list_append(NULL,
- copy_and_terms(g_list_nth_data(q->terms, 0)));
-
- iright = qof_query_invert(right);
- ileft = qof_query_invert(left);
-
- retval = qof_query_merge(iright, ileft, QOF_QUERY_AND);
- retval->books = g_list_copy (q->books);
- retval->max_results = q->max_results;
- retval->search_for = q->search_for;
- retval->changed = 1;
-
- qof_query_destroy(iright);
- qof_query_destroy(ileft);
- qof_query_destroy(right);
- qof_query_destroy(left);
- break;
- }
-
- return retval;
-}
-
-/********************************************************************
- * qof_query_merge
- * combine 2 Query objects by the logical operation in "op".
- ********************************************************************/
-
-QofQuery *
-qof_query_merge(QofQuery *q1, QofQuery *q2, QofQueryOp op)
-{
-
- QofQuery * retval = NULL;
- QofQuery * i1, * i2;
- QofQuery * t1, * t2;
- GList * i, * j;
- QofIdType search_for;
-
- if(!q1) return q2;
- if(!q2) return q1;
-
- if (q1->search_for && q2->search_for)
- g_return_val_if_fail (safe_strcmp (q1->search_for, q2->search_for) == 0,
- NULL);
-
- search_for = (q1->search_for ? q1->search_for : q2->search_for);
-
- /* Avoid merge surprises if op==QOF_QUERY_AND but q1 is empty.
- * The goal of this tweak is to all the user to start with
- * an empty q1 and then append to it recursively
- * (and q1 (and q2 (and q3 (and q4 ....))))
- * without bombing out because the append started with an
- * empty list.
- * We do essentially the same check in qof_query_add_term()
- * so that the first term added to an empty query doesn't screw up.
- */
- if ((QOF_QUERY_AND == op) && (0 == qof_query_has_terms (q1)))
- {
- op = QOF_QUERY_OR;
- }
-
- switch(op)
- {
- case QOF_QUERY_OR:
- retval = qof_query_create();
- retval->terms =
- g_list_concat(copy_or_terms(q1->terms), copy_or_terms(q2->terms));
- retval->books = merge_books (q1->books, q2->books);
- retval->max_results = q1->max_results;
- retval->changed = 1;
- break;
-
- case QOF_QUERY_AND:
- retval = qof_query_create();
- retval->books = merge_books (q1->books, q2->books);
- retval->max_results = q1->max_results;
- retval->changed = 1;
-
- /* g_list_append() can take forever, so let's build the list in
- * reverse and then reverse it at the end, to deal better with
- * "large" queries.
- */
- for(i=q1->terms; i; i=i->next)
- {
- for(j=q2->terms; j; j=j->next)
- {
- retval->terms =
- g_list_prepend(retval->terms,
- g_list_concat
- (copy_and_terms(i->data),
- copy_and_terms(j->data)));
- }
- }
- retval->terms = g_list_reverse(retval->terms);
- break;
-
- case QOF_QUERY_NAND:
- /* !(a*b) = (!a + !b) */
- i1 = qof_query_invert(q1);
- i2 = qof_query_invert(q2);
- retval = qof_query_merge(i1, i2, QOF_QUERY_OR);
- qof_query_destroy(i1);
- qof_query_destroy(i2);
- break;
-
- case QOF_QUERY_NOR:
- /* !(a+b) = (!a*!b) */
- i1 = qof_query_invert(q1);
- i2 = qof_query_invert(q2);
- retval = qof_query_merge(i1, i2, QOF_QUERY_AND);
- qof_query_destroy(i1);
- qof_query_destroy(i2);
- break;
-
- case QOF_QUERY_XOR:
- /* a xor b = (a * !b) + (!a * b) */
- i1 = qof_query_invert(q1);
- i2 = qof_query_invert(q2);
- t1 = qof_query_merge(q1, i2, QOF_QUERY_AND);
- t2 = qof_query_merge(i1, q2, QOF_QUERY_AND);
- retval = qof_query_merge(t1, t2, QOF_QUERY_OR);
-
- qof_query_destroy(i1);
- qof_query_destroy(i2);
- qof_query_destroy(t1);
- qof_query_destroy(t2);
- break;
- }
-
- retval->search_for = search_for;
- return retval;
-}
-
-void
-qof_query_merge_in_place(QofQuery *q1, QofQuery *q2, QofQueryOp op)
-{
- QofQuery *tmp_q;
-
- if (!q1 || !q2)
- return;
-
- tmp_q = qof_query_merge (q1, q2, op);
- swap_terms (q1, tmp_q);
- qof_query_destroy (tmp_q);
-}
-
-void
-qof_query_set_sort_order (QofQuery *q,
- GSList *params1, GSList *params2, GSList *params3)
-{
- if (!q) return;
- if (q->primary_sort.param_list)
- g_slist_free (q->primary_sort.param_list);
- q->primary_sort.param_list = params1;
- q->primary_sort.options = 0;
-
- if (q->secondary_sort.param_list)
- g_slist_free (q->secondary_sort.param_list);
- q->secondary_sort.param_list = params2;
- q->secondary_sort.options = 0;
-
- if (q->tertiary_sort.param_list)
- g_slist_free (q->tertiary_sort.param_list);
- q->tertiary_sort.param_list = params3;
- q->tertiary_sort.options = 0;
-
- q->changed = 1;
-}
-
-void qof_query_set_sort_options (QofQuery *q, gint prim_op, gint sec_op,
- gint tert_op)
-{
- if (!q) return;
- q->primary_sort.options = prim_op;
- q->secondary_sort.options = sec_op;
- q->tertiary_sort.options = tert_op;
-}
-
-void qof_query_set_sort_increasing (QofQuery *q, gboolean prim_inc,
- gboolean sec_inc, gboolean tert_inc)
-{
- if (!q) return;
- q->primary_sort.increasing = prim_inc;
- q->secondary_sort.increasing = sec_inc;
- q->tertiary_sort.increasing = tert_inc;
-}
-
-void qof_query_set_max_results (QofQuery *q, int n)
-{
- if (!q) return;
- q->max_results = n;
-}
-
-void qof_query_add_guid_list_match (QofQuery *q, GSList *param_list,
- GList *guid_list, QofGuidMatch options,
- QofQueryOp op)
-{
- QofQueryPredData *pdata;
-
- if (!q || !param_list) return;
-
- if (!guid_list)
- g_return_if_fail (options == QOF_GUID_MATCH_NULL);
-
- pdata = qof_query_guid_predicate (options, guid_list);
- qof_query_add_term (q, param_list, pdata, op);
-}
-
-void qof_query_add_guid_match (QofQuery *q, GSList *param_list,
- const GUID *guid, QofQueryOp op)
-{
- GList *g = NULL;
-
- if (!q || !param_list) return;
-
- if (guid)
- g = g_list_prepend (g, (gpointer)guid);
-
- qof_query_add_guid_list_match (q, param_list, g,
- g ? QOF_GUID_MATCH_ANY : QOF_GUID_MATCH_NULL, op);
-
- g_list_free (g);
-}
-
-void qof_query_set_book (QofQuery *q, QofBook *book)
-{
- GSList *slist = NULL;
- if (!q || !book) return;
-
- /* Make sure this book is only in the list once */
- if (g_list_index (q->books, book) == -1)
- q->books = g_list_prepend (q->books, book);
-
- g_slist_prepend (slist, QOF_PARAM_GUID);
- g_slist_prepend (slist, QOF_PARAM_BOOK);
- qof_query_add_guid_match (q, slist,
- qof_book_get_guid(book), QOF_QUERY_AND);
-}
-
-GList * qof_query_get_books (QofQuery *q)
-{
- if (!q) return NULL;
- return q->books;
-}
-
-void qof_query_add_boolean_match (QofQuery *q, GSList *param_list, gboolean value,
- QofQueryOp op)
-{
- QofQueryPredData *pdata;
- if (!q || !param_list) return;
-
- pdata = qof_query_boolean_predicate (QOF_COMPARE_EQUAL, value);
- qof_query_add_term (q, param_list, pdata, op);
-}
-
-/**********************************************************************/
-/* PRIVATE PUBLISHED API FUNCTIONS */
-
-void qof_query_init (void)
-{
- ENTER (" ");
- qof_query_core_init ();
- qof_class_init ();
-}
-
-void qof_query_shutdown (void)
-{
- qof_class_shutdown ();
- qof_query_core_shutdown ();
-}
-
-int qof_query_get_max_results (QofQuery *q)
-{
- if (!q) return 0;
- return q->max_results;
-}
-
-QofIdType qof_query_get_search_for (QofQuery *q)
-{
- if (!q) return NULL;
- return q->search_for;
-}
-
-GList * qof_query_get_terms (QofQuery *q)
-{
- if (!q) return NULL;
- return q->terms;
-}
-
-GSList * qof_query_term_get_param_path (QofQueryTerm *qt)
-{
- if (!qt)
- return NULL;
- return qt->param_list;
-}
-
-QofQueryPredData *qof_query_term_get_pred_data (QofQueryTerm *qt)
-{
- if (!qt)
- return NULL;
- return qt->pdata;
-}
-
-gboolean qof_query_term_is_inverted (QofQueryTerm *qt)
-{
- if (!qt)
- return FALSE;
- return qt->invert;
-}
-
-void qof_query_get_sorts (QofQuery *q, QofQuerySort **primary,
- QofQuerySort **secondary, QofQuerySort **tertiary)
-{
- if (!q)
- return;
- if (primary)
- *primary = &(q->primary_sort);
- if (secondary)
- *secondary = &(q->secondary_sort);
- if (tertiary)
- *tertiary = &(q->tertiary_sort);
-}
-
-GSList * qof_query_sort_get_param_path (QofQuerySort *qs)
-{
- if (!qs)
- return NULL;
- return qs->param_list;
-}
-
-gint qof_query_sort_get_sort_options (QofQuerySort *qs)
-{
- if (!qs)
- return 0;
- return qs->options;
-}
-
-gboolean qof_query_sort_get_increasing (QofQuerySort *qs)
-{
- if (!qs)
- return FALSE;
- return qs->increasing;
-}
-
-static gboolean
-qof_query_term_equal (QofQueryTerm *qt1, QofQueryTerm *qt2)
-{
- if (qt1 == qt2) return TRUE;
- if (!qt1 || !qt2) return FALSE;
-
- if (qt1->invert != qt2->invert) return FALSE;
- if (param_list_cmp (qt1->param_list, qt2->param_list)) return FALSE;
- return qof_query_core_predicate_equal (qt1->pdata, qt2->pdata);
-}
-
-static gboolean
-qof_query_sort_equal (QofQuerySort* qs1, QofQuerySort* qs2)
-{
- if (qs1 == qs2) return TRUE;
- if (!qs1 || !qs2) return FALSE;
-
- /* "Empty" sorts are equivalent, regardless of the flags */
- if (!qs1->param_list && !qs2->param_list) return TRUE;
-
- if (qs1->options != qs2->options) return FALSE;
- if (qs1->increasing != qs2->increasing) return FALSE;
- return (param_list_cmp (qs1->param_list, qs2->param_list) == 0);
-}
-
-gboolean qof_query_equal (QofQuery *q1, QofQuery *q2)
-{
- GList *or1, *or2;
-
- if (q1 == q2) return TRUE;
- if (!q1 || !q2) return FALSE;
-
- if (g_list_length (q1->terms) != g_list_length (q2->terms)) return FALSE;
- if (q1->max_results != q2->max_results) return FALSE;
-
- for (or1 = q1->terms, or2 = q2->terms; or1;
- or1 = or1->next, or2 = or2->next)
- {
- GList *and1, *and2;
-
- and1 = or1->data;
- and2 = or2->data;
-
- if (g_list_length (and1) != g_list_length (and2)) return FALSE;
-
- for ( ; and1; and1 = and1->next, and2 = and2->next)
- if (!qof_query_term_equal (and1->data, and2->data))
- return FALSE;
- }
-
- if (!qof_query_sort_equal (&(q1->primary_sort), &(q2->primary_sort)))
- return FALSE;
- if (!qof_query_sort_equal (&(q1->secondary_sort), &(q2->secondary_sort)))
- return FALSE;
- if (!qof_query_sort_equal (&(q1->tertiary_sort), &(q2->tertiary_sort)))
- return FALSE;
-
- return TRUE;
-}
-
-/***************************************************************************/
-/***************************************************************************/
-/* Query Print functions. qof_query_print is public; everthing else supports
- * that.
- * Just call qof_query_print(QofQuery *q), and it will print out the query
- * contents to stderr.
-*/
-
-/* Static prototypes */
-static GList *qof_query_printSearchFor (QofQuery * query, GList * output);
-static GList *qof_query_printTerms (QofQuery * query, GList * output);
-static GList *qof_query_printSorts (QofQuerySort *s[], const gint numSorts,
- GList * output);
-static GList *qof_query_printAndTerms (GList * terms, GList * output);
-static gchar *qof_query_printStringForHow (QofQueryCompare how);
-static gchar *qof_query_printStringMatch (QofStringMatch s);
-static gchar *qof_query_printDateMatch (QofDateMatch d);
-static gchar *qof_query_printNumericMatch (QofNumericMatch n);
-static gchar *qof_query_printGuidMatch (QofGuidMatch g);
-static gchar *qof_query_printCharMatch (QofCharMatch c);
-static GString *qof_query_printPredData (QofQueryPredData *pd);
-static GString *qof_query_printParamPath (GSList * parmList);
-static void qof_query_printValueForParam (QofQueryPredData *pd, GString * gs);
-static void qof_query_printOutput (GList * output);
-
-/*
- This function cycles through a QofQuery object, and
- prints out the values of the various members of the query
-*/
-void
-qof_query_print (QofQuery * query)
-{
- GList *output;
- GString *str;
- QofQuerySort *s[3];
- gint maxResults = 0, numSorts = 3;
-
- ENTER (" ");
-
- if (!query) {
- LEAVE("query is (null)");
- return;
- }
-
- output = NULL;
- str = NULL;
- maxResults = qof_query_get_max_results (query);
-
- output = qof_query_printSearchFor (query, output);
- output = qof_query_printTerms (query, output);
-
- qof_query_get_sorts (query, &s[0], &s[1], &s[2]);
-
- if (s[0])
- {
- output = qof_query_printSorts (s, numSorts, output);
- }
-
- str = g_string_new (" ");
- g_string_sprintf (str, "Maximum number of results: %d", maxResults);
- output = g_list_append (output, str);
-
- qof_query_printOutput (output);
- LEAVE (" ");
-}
-
-static void
-qof_query_printOutput (GList * output)
-{
- GList *lst;
-
- for (lst = output; lst; lst = lst->next)
- {
- GString *line = (GString *) lst->data;
-
- fprintf (stderr, "%s\n", line->str);
- g_string_free (line, TRUE);
- line = NULL;
- }
-}
-
-/*
- Get the search_for type--This is the type of Object
- we are searching for (SPLIT, TRANS, etc)
-*/
-static GList *
-qof_query_printSearchFor (QofQuery * query, GList * output)
-{
- QofIdType searchFor;
- GString *gs;
-
- searchFor = qof_query_get_search_for (query);
- gs = g_string_new ("Query Object Type: ");
- g_string_append (gs, (NULL == searchFor)? "(null)" : searchFor);
- output = g_list_append (output, gs);
-
- return output;
-} /* qof_query_printSearchFor */
-
-/*
- Run through the terms of the query. This is a outer-inner
- loop. The elements of the outer loop are ORed, and the
- elements of the inner loop are ANDed.
-*/
-static GList *
-qof_query_printTerms (QofQuery * query, GList * output)
-{
-
- GList *terms, *lst;
-
- terms = qof_query_get_terms (query);
-
- for (lst = terms; lst; lst = lst->next)
- {
- output = g_list_append (output, g_string_new ("OR and AND Terms:"));
-
- if (lst->data)
- {
- output = qof_query_printAndTerms (lst->data, output);
- }
- else
- {
- output =
- g_list_append (output, g_string_new (" No data for AND terms"));
- }
- }
-
- return output;
-} /* qof_query_printTerms */
-
-/*
- Process the sort parameters
- If this function is called, the assumption is that the first sort
- not null.
-*/
-static GList *
-qof_query_printSorts (QofQuerySort *s[], const gint numSorts, GList * output)
-{
- GSList *gsl, *n = NULL;
- gint curSort;
- GString *gs = g_string_new (" Sort Parameters:\n");
-
- for (curSort = 0; curSort < numSorts; curSort++)
- {
- gboolean increasing;
- if (!s[curSort])
- {
- break;
- }
- increasing = qof_query_sort_get_increasing (s[curSort]);
-
- gsl = qof_query_sort_get_param_path (s[curSort]);
- if (gsl) g_string_sprintfa (gs, " Param: ");
- for (n=gsl; n; n = n->next)
- {
- QofIdType param_name = n->data;
- if (gsl != n)g_string_sprintfa (gs, "\n ");
- g_string_sprintfa (gs, "%s", param_name);
- }
- if (gsl)
- {
- g_string_sprintfa (gs, " %s\n", increasing ? "DESC" : "ASC");
- g_string_sprintfa (gs, " Options: 0x%x\n", s[curSort]->options);
- }
- }
-
- output = g_list_append (output, gs);
- return output;
-
-} /* qof_query_printSorts */
-
-/*
- Process the AND terms of the query. This is a GList
- of WHERE terms that will be ANDed
-*/
-static GList *
-qof_query_printAndTerms (GList * terms, GList * output)
-{
- const char *prefix = " AND Terms:";
- QofQueryTerm *qt;
- QofQueryPredData *pd;
- GSList *path;
- GList *lst;
- gboolean invert;
-
- output = g_list_append (output, g_string_new (prefix));
- for (lst = terms; lst; lst = lst->next)
- {
- qt = (QofQueryTerm *) lst->data;
- pd = qof_query_term_get_pred_data (qt);
- path = qof_query_term_get_param_path (qt);
- invert = qof_query_term_is_inverted (qt);
-
- if (invert) output = g_list_append (output,
- g_string_new(" INVERT SENSE "));
- output = g_list_append (output, qof_query_printParamPath (path));
- output = g_list_append (output, qof_query_printPredData (pd));
- output = g_list_append (output, g_string_new("\n"));
- }
-
- return output;
-} /* qof_query_printAndTerms */
-
-/*
- Process the parameter types of the predicate data
-*/
-static GString *
-qof_query_printParamPath (GSList * parmList)
-{
- GSList *list = NULL;
- GString *gs = g_string_new (" Param List:\n");
- g_string_append (gs, " ");
- for (list = parmList; list; list = list->next)
- {
- g_string_append (gs, (gchar *) list->data);
- if (list->next)
- g_string_append (gs, "->");
- }
-
- return gs;
-} /* qof_query_printParamPath */
-
-/*
- Process the PredData of the AND terms
-*/
-static GString *
-qof_query_printPredData (QofQueryPredData *pd)
-{
- GString *gs;
-
- gs = g_string_new (" Pred Data:\n ");
- g_string_append (gs, (gchar *) pd->type_name);
-
- /* Char Predicate and GUID predicate don't use the 'how' field. */
- if (safe_strcmp (pd->type_name, QOF_TYPE_CHAR) &&
- safe_strcmp (pd->type_name, QOF_TYPE_GUID))
- {
- g_string_sprintfa (gs, "\n how: %s",
- qof_query_printStringForHow (pd->how));
- }
-
- qof_query_printValueForParam (pd, gs);
-
- return gs;
-} /* qof_query_printPredData */
-
-/*
- Get a string representation for the
- QofCompareFunc enum type.
-*/
-static gchar *
-qof_query_printStringForHow (QofQueryCompare how)
-{
-
- switch (how)
- {
- case QOF_COMPARE_LT:
- return "QOF_COMPARE_LT";
- case QOF_COMPARE_LTE:
- return "QOF_COMPARE_LTE";
- case QOF_COMPARE_EQUAL:
- return "QOF_COMPARE_EQUAL";
- case QOF_COMPARE_GT:
- return "QOF_COMPARE_GT";
- case QOF_COMPARE_GTE:
- return "QOF_COMPARE_GTE";
- case QOF_COMPARE_NEQ:
- return "QOF_COMPARE_NEQ";
- }
-
- return "INVALID HOW";
-} /* qncQueryPrintStringForHow */
-
-
-static void
-qof_query_printValueForParam (QofQueryPredData *pd, GString * gs)
-{
-
- if (!safe_strcmp (pd->type_name, QOF_TYPE_GUID))
- {
- GList *node;
- query_guid_t pdata = (query_guid_t) pd;
- g_string_sprintfa (gs, "\n Match type %s",
- qof_query_printGuidMatch (pdata->options));
- for (node = pdata->guids; node; node = node->next)
- {
- /* THREAD-UNSAFE */
- g_string_sprintfa (gs, ", guids: %s",
- guid_to_string ((GUID *) node->data));
- }
- return;
- }
- if (!safe_strcmp (pd->type_name, QOF_TYPE_STRING))
- {
- query_string_t pdata = (query_string_t) pd;
- g_string_sprintfa (gs, "\n Match type %s",
- qof_query_printStringMatch (pdata->options));
- g_string_sprintfa (gs, " %s string: %s",
- pdata->is_regex ? "Regex" : "Not regex",
- pdata->matchstring);
- return;
- }
- if (!safe_strcmp (pd->type_name, QOF_TYPE_NUMERIC))
- {
- query_numeric_t pdata = (query_numeric_t) pd;
- g_string_sprintfa (gs, "\n Match type %s",
- qof_query_printNumericMatch (pdata->options));
- g_string_sprintfa (gs, " gnc_numeric: %s",
- gnc_num_dbg_to_string (pdata->amount));
- return;
- }
- if (!safe_strcmp (pd->type_name, QOF_TYPE_KVP))
- {
- GSList *node;
- query_kvp_t pdata = (query_kvp_t) pd;
- g_string_sprintfa (gs, "\n kvp path: ");
- for (node = pdata->path; node; node = node->next)
- {
- g_string_sprintfa (gs, "/%s", (gchar *) node->data);
- }
- g_string_sprintfa (gs, "\n");
- g_string_sprintfa (gs, " kvp value: %s\n",
- kvp_value_to_string (pdata->value));
- return;
- }
- if (!safe_strcmp (pd->type_name, QOF_TYPE_INT64))
- {
- query_int64_t pdata = (query_int64_t) pd;
- g_string_sprintfa (gs, " int64: %" G_GINT64_FORMAT, pdata->val);
- return;
- }
- if (!safe_strcmp (pd->type_name, QOF_TYPE_INT32))
- {
- query_int32_t pdata = (query_int32_t) pd;
- g_string_sprintfa (gs, " int32: %d", pdata->val);
- return;
- }
- if (!safe_strcmp (pd->type_name, QOF_TYPE_DOUBLE))
- {
- query_double_t pdata = (query_double_t) pd;
- g_string_sprintfa (gs, " double: %.18g", pdata->val);
- return;
- }
- if (!safe_strcmp (pd->type_name, QOF_TYPE_DATE))
- {
- query_date_t pdata = (query_date_t) pd;
- g_string_sprintfa (gs, "\n Match type %s",
- qof_query_printDateMatch (pdata->options));
- g_string_sprintfa (gs, " query_date: %s", gnc_print_date (pdata->date));
- return;
- }
- if (!safe_strcmp (pd->type_name, QOF_TYPE_CHAR))
- {
- query_char_t pdata = (query_char_t) pd;
- g_string_sprintfa (gs, "\n Match type %s",
- qof_query_printCharMatch (pdata->options));
- g_string_sprintfa (gs, " char list: %s", pdata->char_list);
- return;
- }
- if (!safe_strcmp (pd->type_name, QOF_TYPE_BOOLEAN))
- {
- query_boolean_t pdata = (query_boolean_t) pd;
- g_string_sprintfa (gs, " boolean: %s", pdata->val?"TRUE":"FALSE");
- return;
- }
- /** \todo QOF_TYPE_COLLECT */
- return;
-} /* qof_query_printValueForParam */
-
-/*
- * Print out a string representation of the
- * QofStringMatch enum
- */
-static gchar *
-qof_query_printStringMatch (QofStringMatch s)
-{
- switch (s)
- {
- case QOF_STRING_MATCH_NORMAL:
- return "QOF_STRING_MATCH_NORMAL";
- case QOF_STRING_MATCH_CASEINSENSITIVE:
- return "QOF_STRING_MATCH_CASEINSENSITIVE";
- }
- return "UNKNOWN MATCH TYPE";
-} /* qof_query_printStringMatch */
-
-/*
- * Print out a string representation of the
- * QofDateMatch enum
- */
-static gchar *
-qof_query_printDateMatch (QofDateMatch d)
-{
- switch (d)
- {
- case QOF_DATE_MATCH_NORMAL:
- return "QOF_DATE_MATCH_NORMAL";
- case QOF_DATE_MATCH_DAY:
- return "QOF_DATE_MATCH_DAY";
- }
- return "UNKNOWN MATCH TYPE";
-} /* qof_query_printDateMatch */
-
-/*
- * Print out a string representation of the
- * QofNumericMatch enum
- */
-static gchar *
-qof_query_printNumericMatch (QofNumericMatch n)
-{
- switch (n)
- {
- case QOF_NUMERIC_MATCH_DEBIT:
- return "QOF_NUMERIC_MATCH_DEBIT";
- case QOF_NUMERIC_MATCH_CREDIT:
- return "QOF_NUMERIC_MATCH_CREDIT";
- case QOF_NUMERIC_MATCH_ANY:
- return "QOF_NUMERIC_MATCH_ANY";
- }
- return "UNKNOWN MATCH TYPE";
-} /* qof_query_printNumericMatch */
-
-/*
- * Print out a string representation of the
- * QofGuidMatch enum
- */
-static gchar *
-qof_query_printGuidMatch (QofGuidMatch g)
-{
- switch (g)
- {
- case QOF_GUID_MATCH_ANY:
- return "QOF_GUID_MATCH_ANY";
- case QOF_GUID_MATCH_ALL:
- return "QOF_GUID_MATCH_ALL";
- case QOF_GUID_MATCH_NONE:
- return "QOF_GUID_MATCH_NONE";
- case QOF_GUID_MATCH_NULL:
- return "QOF_GUID_MATCH_NULL";
- case QOF_GUID_MATCH_LIST_ANY:
- return "QOF_GUID_MATCH_LIST_ANY";
- }
-
- return "UNKNOWN MATCH TYPE";
-} /* qof_query_printGuidMatch */
-
-/*
- * Print out a string representation of the
- * QofCharMatch enum
- */
-static gchar *
-qof_query_printCharMatch (QofCharMatch c)
-{
- switch (c)
- {
- case QOF_CHAR_MATCH_ANY:
- return "QOF_CHAR_MATCH_ANY";
- case QOF_CHAR_MATCH_NONE:
- return "QOF_CHAR_MATCH_NONE";
- }
- return "UNKNOWN MATCH TYPE";
-} /* qof_query_printGuidMatch */
-
-/* ======================== END OF FILE =================== */
Deleted: gnucash/trunk/src/engine/qofquery.h
===================================================================
--- gnucash/trunk/src/engine/qofquery.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofquery.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,375 +0,0 @@
-/********************************************************************\
- * qofquery.h -- find objects that match a certain expression. *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-/** @addtogroup Query
-
-BASIC QUERY API:
-With this API you can create arbitrary logical
-queries to find sets of arbitrary object. To make simple
-queries (1 term, such as a search for a parameter with one value),
-create the appropriate
-QueryTerm structure and stick it in a Query object using
-xaccInitQuery. The QueryTerm should be malloced but the Query object
-will handle freeing it. To make compound queries, make multiple
-simple queries and combine them using qof_query_merge() and the logical
-operations of your choice.
-
-SQL QUERY API:
-As an alternative to building queries one predicate at a time,
-you can use the SQL query interface. This interface will accept
-a string containing an SQL query, parse it, convert it into the
-core representation, and execute it.
-
-STRUCTURE OF A QUERY: A Query is a logical function of any number of
-QueryTerms. A QueryTerm consists of a C function pointer (the
-Predicate) and a PredicateData structure containing data passed to the
-predicate funtion. The PredicateData structure is a constant
-associated with the Term and is identical for every object that is
-tested.
-
-The terms of the Query may represent any logical function and are
-stored in canonical form, i.e. the function is expressed as a logical
-sum of logical products. So if you have QueryTerms a, b, c, d, e and
-you have the logical function a(b+c) + !(c(d+e)), it gets stored as
-ab + ac + !c + !c!e +!d!c + !d!e. This may not be optimal for evaluation
-of some functions but it's easy to store, easy to manipulate, and it
-doesn't require a complete algebra system to deal with.
-
-The representation is of a GList of GLists of QueryTerms. The
-"backbone" GList q->terms represents the OR-chain, and every item on
-the backbone is a GList of QueryTerms representing an AND-chain
-corresponding to a single product-term in the canonical
-representation. QueryTerms are duplicated when necessary to fill out
-the canonical form, and the same predicate may be evaluated multiple
-times per split for complex queries. This is a place where we could
-probably optimize.
-
-Evaluation of a Query (see qof_query_run()) is optimized as much as
-possible by short-circuited evaluation. The predicates in each
-AND-chain are sorted by predicate type, with Account queries sorted
-first to allow the evaluator to completely eliminate accounts from the
-search if there's no chance of them having splits that match.
-(XXX above no longer applies)
-
- @{ */
-/** @file qofquery.h
- @brief find objects that match a certain expression.
- @author Copyright (C) 2002 Derek Atkins <warlord at MIT.EDU>
- @author Copyright (C) 2003 Linas Vepstas <linas at linas.org>
-
-*/
-
-
-#ifndef QOF_QUERYNEW_H
-#define QOF_QUERYNEW_H
-
-#include "guid.h"
-#include "qofbook.h"
-#include "qofquerycore.h"
-#include "qofchoice.h"
-
-#define QOF_MOD_QUERY "qof-query"
-
-/** A Query */
-typedef struct _QofQuery QofQuery;
-
-/** Query Term Operators, for combining Query Terms */
-typedef enum {
- QOF_QUERY_AND=1,
- QOF_QUERY_OR,
- QOF_QUERY_NAND,
- QOF_QUERY_NOR,
- QOF_QUERY_XOR
-} QofQueryOp;
-
-/* First/only term is same as 'and' */
-#define QOF_QUERY_FIRST_TERM QOF_QUERY_AND
-
-/** Default sort object type */
-#define QUERY_DEFAULT_SORT "QofQueryDefaultSort"
-
-/** "Known" Object Parameters -- all objects must support these */
-#define QOF_PARAM_BOOK "book"
-#define QOF_PARAM_GUID "guid"
-
-/** "Known" Object Parameters -- some objects might support these */
-#define QOF_PARAM_KVP "kvp"
-#define QOF_PARAM_ACTIVE "active"
-#define QOF_PARAM_VERSION "version"
-
-/* --------------------------------------------------------- */
-/** \name Query Subsystem Initialization and Shudown */
-// @{
-/** Subsystem initialization and shutdown. Call init() once
- * to initalize the query subsytem; call shutdown() to free
- * up any resources associated with the query subsystem.
- * Typically called during application startup, shutdown.
- */
-
-void qof_query_init (void);
-void qof_query_shutdown (void);
-// @}
-
-/* --------------------------------------------------------- */
-/** \name Low-Level API Functions */
-// @{
-
-GSList * qof_query_build_param_list (char const *param, ...);
-
-/** Create a new query.
- * Before running the query, a 'search-for' type must be set
- * otherwise nothing will be returned. The results of the query
- * is a list of the indicated search-for type.
- *
- * Allocates and initializes a Query structure which must be
- * freed by the user with qof_query_destroy(). A newly-allocated
- * QofQuery object matches nothing (qof_query_run() will return NULL).
- */
-QofQuery * qof_query_create (void);
-QofQuery * qof_query_create_for (QofIdTypeConst obj_type);
-
-/** Frees the resources associate with a Query object. */
-void qof_query_destroy (QofQuery *q);
-
-/** Set the object type to be searched for. The results of
- * performuing the query will be a list of this obj_type.
- */
-void qof_query_search_for (QofQuery *query, QofIdTypeConst obj_type);
-
-/** Set the book to be searched. Books contain/identify collections
- * of objects; the search will be performed over those books
- * specified with this function. If no books are set, no results
- * will be returned (since there is nothing to search over). (CAS:
- * Apparently, if no books are set, you'll actually get a critical
- * assertion failure.)
- *
- * You can search multiple books. To specify multiple books, call
- * this function multiple times with different arguments.
- * XXX needed qof_query_clear_books() to reset the list ...
- */
-void qof_query_set_book (QofQuery *q, QofBook *book);
-
-
-/** This is the general function that adds a new Query Term to a query.
- * It will find the 'obj_type' object of the search item and compare
- * the 'param_list' parameter to the predicate data via the comparitor.
- *
- * The param_list is a recursive list of parameters. For example, you
- * can say 'split->memo' by creating a list of one element, "SPLIT_MEMO".
- * You can say 'split->account->name' by creating a list of two elements,
- * "SPLIT_ACCOUNT" and "ACCOUNT_NAME". The list becomes the property of
- * the Query.
- *
- * For example:
- *
- * acct_name_pred_data = make_string_pred_data(QOF_STRING_MATCH_CASEINSENSITIVE,
- * account_name);
- * param_list = make_list (SPLIT_ACCOUNT, ACCOUNT_NAME, NULL);
- * qof_query_add_term (query, param_list, QOF_COMPARE_EQUAL,
- * acct_name_pred_data, QOF_QUERY_AND);
- *
- * Please note that QofQuery does not, at this time, support joins.
- * That is, one cannot specify a predicate that is a parameter list.
- * Put another way, one cannot search for objects where
- * obja->thingy == objb->stuff
- */
-
-void qof_query_add_term (QofQuery *query, GSList *param_list,
- QofQueryPredData *pred_data, QofQueryOp op);
-
-/** DOCUMENT ME !! */
-void qof_query_add_guid_match (QofQuery *q, GSList *param_list,
- const GUID *guid, QofQueryOp op);
-/** DOCUMENT ME !! */
-void qof_query_add_guid_list_match (QofQuery *q, GSList *param_list,
- GList *guid_list, QofGuidMatch options,
- QofQueryOp op);
-
-/** Handy-dandy convenience routines, avoids having to create
- * a separate predicate for boolean matches. We might want to
- * create handy-dandy sugar routines for the other predicate types
- * as well. */
-void qof_query_add_boolean_match (QofQuery *q,
- GSList *param_list,
- gboolean value,
- QofQueryOp op);
-
-/** Perform the query, return the results.
- * The returned list is a list of the 'search-for' type that was
- * previously set with the qof_query_search_for() or the
- * qof_query_create_for() routines. The returned list will have
- * been sorted using the indicated sort order, and trimed to the
- * max_results length.
- *
- * Do NOT free the resulting list. This list is managed internally
- * by QofQuery.
- */
-GList * qof_query_run (QofQuery *query);
-
-/** Return the results of the last query, without causing the query to
- * be re-run. Do NOT free the resulting list. This list is managed
- * internally by QofQuery.
- */
-GList * qof_query_last_run (QofQuery *query);
-
-/** Remove all query terms from query. query matches nothing
- * after qof_query_clear().
- */
-void qof_query_clear (QofQuery *query);
-
-/** Remove query terms of a particular type from q. The "type" of a term
- * is determined by the type of data that gets passed to the predicate
- * function.
- * XXX ??? Huh? remove anything of that predicate type, or just
- * the particular predicate ?
- */
-void qof_query_purge_terms (QofQuery *q, GSList *param_list);
-
-/** Return boolean FALSE if there are no terms in the query
- * Can be used as a predicate to see if the query has been
- * initialized (return value > 0) or is "blank" (return value == 0).
- */
-int qof_query_has_terms (QofQuery *q);
-
-/** Return the number of terms in the canonical form of the query.
- */
-int qof_query_num_terms (QofQuery *q);
-
-/** DOCUMENT ME !! */
-gboolean qof_query_has_term_type (QofQuery *q, GSList *term_param);
-GSList * qof_query_get_term_type (QofQuery *q, GSList *term_param);
-
-/** Make a copy of the indicated query */
-QofQuery * qof_query_copy (QofQuery *q);
-
-/** Make a copy of the indicated query, inverting the sense
- * of the search. In other words, if the original query search
- * for all objects with a certain condition, the inverted query
- * will search for all object with NOT that condition. The union
- * of the results returned by the original and inverted queries
- * equals the set of all searched objects. These to sets are
- * disjoint (share no members in common).
- *
- * This will return a newly allocated QofQuery object, or NULL
- * on error. Free it with qof_query_destroy() when no longer needed.
- */
-QofQuery * qof_query_invert(QofQuery *q);
-
-/** Combine two queries together using the Boolean set (logical)
- * operator 'op'. For example, if the operator 'op' is set to
- * QUERY_AND, then the set of results returned by the query will
- * will be the Boolean set intersection of the results returned
- * by q1 and q2. Similarly, QUERY_OR maps to set union, etc.
- *
- * Both queries must have compatible
- * search-types. If both queries are set, they must search for the
- * same object type. If only one is set, the resulting query will
- * search for the set type. If neither query has the search-type set,
- * the result will be unset as well.
- *
- * This will return a newly allocated QofQuery object, or NULL
- * on error. Free it with qof_query_destroy() when no longer needed.
- */
-QofQuery * qof_query_merge(QofQuery *q1, QofQuery *q2, QofQueryOp op);
-
-/** Like qof_query_merge, but this will merge a copy of q2 into q1.
- * q2 remains unchanged.
- */
-void qof_query_merge_in_place(QofQuery *q1, QofQuery *q2, QofQueryOp op);
-
-/**
- * When a query is run, the results are sorted before being returned.
- * This routine can be used to set the paramters on which the sort will
- * be performed. Two objects in the result list will be compared using
- * the 'primary_sort_params', and sorted based on that order. If the
- * comparison shows that they are equal, then the
- * 'secondary_sort_params' will be used. If still equal, then the
- * tertiary params will be compared. Any or all of these parameter
- * lists may be NULL. Any of these parameter lists may be set to
- * QUERY_DEFAULT_SORT.
- *
- * Note that if there are more results than the 'max-results' value,
- * then only the *last* max-results will be returned. For example,
- * if the sort is set to be increasing date order, then only the
- * objects with the most recent dates will be returned.
- *
- * The input lists become the property of QofQuery and are managed
- * by it. They will be freed when the query is destroyed (or when
- * new lists are set).
- */
-void qof_query_set_sort_order (QofQuery *q,
- GSList *primary_sort_params,
- GSList *secondary_sort_params,
- GSList *tertiary_sort_params);
-
-void qof_query_set_sort_options (QofQuery *q, gint prim_op, gint sec_op,
- gint tert_op);
-
-/**
- * When a query is run, the results are sorted before being returned.
- * This routine can be used to control the direction of the ordering.
- * A value of TRUE indicates the sort will be in increasing order,
- * a value of FALSE will order results in decreasing order.
- *
- * Note that if there are more results than the 'max-results' value,
- * then only the *last* max-results will be returned. For example,
- * if the sort is set to be increasing date order, then only the
- * objects with the most recent dates will be returned.
- */
-void qof_query_set_sort_increasing (QofQuery *q, gboolean prim_inc,
- gboolean sec_inc, gboolean tert_inc);
-
-
-/**
- * Set the maximum number of results that should be returned.
- * If 'max-results' is set to -1, then all of the results are
- * returned. If there are more results than 'max-results',
- * then the result list is trimmed. Note that there is an
- * important interplay between 'max-results' and the sort order:
- * only the last bit of results are returned. For example,
- * if the sort order is set to be increasing date order, then
- * only the objects with the most recent dates will be returned.
- */
-void qof_query_set_max_results (QofQuery *q, int n);
-
-/** Compare two queries for equality.
- * Query terms are compared each to each.
- * This is a simplistic
- * implementation -- logical equivalences between different
- * and/or trees are ignored.
- */
-gboolean qof_query_equal (QofQuery *q1, QofQuery *q2);
-
-/** Print the Query in human-readable format.
- * Useful for debugging and development.
- */
-void qof_query_print (QofQuery *query);
-
-/** Return the type of data we're querying for */
-QofIdType qof_query_get_search_for (QofQuery *q);
-
-/** Return the list of books we're using */
-GList * qof_query_get_books (QofQuery *q);
-
-// @}
-/* @} */
-#endif /* QOF_QUERYNEW_H */
Deleted: gnucash/trunk/src/engine/qofquerycore-p.h
===================================================================
--- gnucash/trunk/src/engine/qofquerycore-p.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofquerycore-p.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,146 +0,0 @@
-/********************************************************************\
- * qofquerycore-p.h -- Private API for providing core Query data types *
- * Copyright (C) 2002 Derek Atkins <warlord at MIT.EDU> *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-#ifndef QOF_QUERYCOREP_H
-#define QOF_QUERYCOREP_H
-
-#include <sys/types.h>
-#include <time.h>
-#include <glib.h>
-#include <regex.h>
-#include <string.h>
-
-#include "qofquerycore.h"
-
-/* Initalize the Query Core registry and install the default type handlers */
-void qof_query_core_init(void);
-void qof_query_core_shutdown (void);
-
-/*
- * An arbitrary Query Predicate. Given the object and the
- * particular parameter get-function (obtained from the registry by
- * the Query internals), compare the object's parameter to the
- * predicate data.
- */
-typedef int (*QofQueryPredicateFunc) (gpointer object,
- QofParam *getter,
- QofQueryPredData *pdata);
-
-/* A callback for how to compare two (same-type) objects based on a
- * common getter (parameter member), using the provided comparison
- * options (which are the type-specific options).
- */
-typedef int (*QofCompareFunc) (gpointer a, gpointer b,
- gint compare_options,
- QofParam *getter);
-
-/* Lookup functions */
-QofQueryPredicateFunc qof_query_core_get_predicate (char const *type);
-QofCompareFunc qof_query_core_get_compare (char const *type);
-
-/* Compare two predicates */
-gboolean qof_query_core_predicate_equal (QofQueryPredData *p1, QofQueryPredData *p2);
-
-/* Predicate Data Structures:
- *
- * These are defined such that you can cast between these types and
- * a QofQueryPredData.
- *
- * Note that these are provided for READ ONLY PURPOSES. You should NEVER
- * write into these structures, change them, or use them to create a
- * Query.
- */
-
-typedef struct {
- QofQueryPredData pd;
- QofStringMatch options;
- gboolean is_regex;
- char * matchstring;
- regex_t compiled;
-} query_string_def, *query_string_t;
-
-typedef struct {
- QofQueryPredData pd;
- QofDateMatch options;
- Timespec date;
-} query_date_def, *query_date_t;
-
-typedef struct {
- QofQueryPredData pd;
- QofNumericMatch options;
- gnc_numeric amount;
-} query_numeric_def, *query_numeric_t;
-
-typedef struct {
- QofQueryPredData pd;
- QofGuidMatch options;
- GList * guids;
-} query_guid_def, *query_guid_t;
-
-typedef struct {
- QofQueryPredData pd;
- gint32 val;
-} query_int32_def, *query_int32_t;
-
-typedef struct {
- QofQueryPredData pd;
- gint64 val;
-} query_int64_def, *query_int64_t;
-
-typedef struct {
- QofQueryPredData pd;
- double val;
-} query_double_def, *query_double_t;
-
-typedef struct {
- QofQueryPredData pd;
- gboolean val;
-} query_boolean_def, *query_boolean_t;
-
-typedef struct {
- QofQueryPredData pd;
- QofCharMatch options;
- char * char_list;
-} query_char_def, *query_char_t;
-
-typedef struct {
- QofQueryPredData pd;
- GSList * path;
- KvpValue * value;
-} query_kvp_def, *query_kvp_t;
-
-typedef struct {
- QofQueryPredData pd;
- QofGuidMatch options;
- QofCollection *coll;
- GList *guids;
-} query_coll_def, *query_coll_t;
-
-typedef struct {
- QofQueryPredData pd;
- QofGuidMatch options;
- const GUID *guid;
- GList * guids;
-} query_choice_def, *query_choice_t;
-
-#endif /* QOF_QUERYCOREP_H */
Deleted: gnucash/trunk/src/engine/qofquerycore.c
===================================================================
--- gnucash/trunk/src/engine/qofquerycore.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofquerycore.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,1834 +0,0 @@
-/********************************************************************\
- * QueryCore.c -- API for providing core Query data types *
- * Copyright (C) 2002 Derek Atkins <warlord at MIT.EDU> *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-#include "config.h"
-
-#include <glib.h>
-
-#include "gnc-trace.h"
-#include "gnc-engine-util.h"
-#include "qofquery.h"
-#include "qofquerycore.h"
-#include "qofquerycore-p.h"
-
-static QofLogModule log_module = QOF_MOD_QUERY;
-
-/* A function to destroy a query predicate's pdata */
-typedef void (*QueryPredDataFree) (QofQueryPredData *pdata);
-
-/* A function to copy a query's predicate data */
-typedef QofQueryPredData *(*QueryPredicateCopyFunc) (QofQueryPredData *pdata);
-
-/* A function to take the object, apply the getter->param_getfcn,
- * and return a printable string. Note that this QofParam->getfnc
- * function should be returning a type equal to this core object type.
- *
- * Note that this string MUST be freed by the caller.
- */
-typedef char * (*QueryToString) (gpointer object, QofParam *getter);
-
-/* A function to test for equality of predicate data */
-typedef gboolean (*QueryPredicateEqual) (QofQueryPredData *p1,
- QofQueryPredData *p2);
-
-static QueryPredicateCopyFunc qof_query_copy_predicate (QofType type);
-static QueryPredDataFree qof_query_predicate_free (QofType type);
-
-/* Core Type Predicate helpers */
-typedef const char * (*query_string_getter) (gpointer, QofParam *);
-static const char * query_string_type = QOF_TYPE_STRING;
-
-typedef Timespec (*query_date_getter) (gpointer, QofParam *);
-static const char * query_date_type = QOF_TYPE_DATE;
-
-typedef gnc_numeric (*query_numeric_getter) (gpointer, QofParam *);
-static const char * query_numeric_type = QOF_TYPE_NUMERIC;
-
-typedef GList * (*query_glist_getter) (gpointer, QofParam *);
-typedef const GUID * (*query_guid_getter) (gpointer, QofParam *);
-static const char * query_guid_type = QOF_TYPE_GUID;
-
-typedef gint32 (*query_int32_getter) (gpointer, QofParam *);
-static const char * query_int32_type = QOF_TYPE_INT32;
-
-typedef gint64 (*query_int64_getter) (gpointer, QofParam *);
-static const char * query_int64_type = QOF_TYPE_INT64;
-
-typedef double (*query_double_getter) (gpointer, QofParam *);
-static const char * query_double_type = QOF_TYPE_DOUBLE;
-
-typedef gboolean (*query_boolean_getter) (gpointer, QofParam *);
-static const char * query_boolean_type = QOF_TYPE_BOOLEAN;
-
-typedef char (*query_char_getter) (gpointer, QofParam *);
-static const char * query_char_type = QOF_TYPE_CHAR;
-
-typedef KvpFrame * (*query_kvp_getter) (gpointer, QofParam *);
-static const char * query_kvp_type = QOF_TYPE_KVP;
-
-typedef QofCollection * (*query_collect_getter) (gpointer, QofParam*);
-static const char * query_collect_type = QOF_TYPE_COLLECT;
-
-typedef const GUID * (*query_choice_getter) (gpointer, QofParam *);
-static const char * query_choice_type = QOF_TYPE_CHOICE;
-
-/* Tables for predicate storage and lookup */
-static gboolean initialized = FALSE;
-static GHashTable *predTable = NULL;
-static GHashTable *cmpTable = NULL;
-static GHashTable *copyTable = NULL;
-static GHashTable *freeTable = NULL;
-static GHashTable *toStringTable = NULL;
-static GHashTable *predEqualTable = NULL;
-
-#define COMPARE_ERROR -3
-#define PREDICATE_ERROR -2
-
-#define VERIFY_PDATA(str) { \
- g_return_if_fail (pd != NULL); \
- g_return_if_fail (pd->type_name == str || \
- !safe_strcmp (str, pd->type_name)); \
-}
-#define VERIFY_PDATA_R(str) { \
- g_return_val_if_fail (pd != NULL, NULL); \
- g_return_val_if_fail (pd->type_name == str || \
- !safe_strcmp (str, pd->type_name), \
- NULL); \
-}
-#define VERIFY_PREDICATE(str) { \
- g_return_val_if_fail (getter != NULL, PREDICATE_ERROR); \
- g_return_val_if_fail (getter->param_getfcn != NULL, PREDICATE_ERROR); \
- g_return_val_if_fail (pd != NULL, PREDICATE_ERROR); \
- g_return_val_if_fail (pd->type_name == str || \
- !safe_strcmp (str, pd->type_name), \
- PREDICATE_ERROR); \
-}
-
-/********************************************************************/
-/* TYPE-HANDLING FUNCTIONS */
-
-/* QOF_TYPE_STRING */
-
-static int
-string_match_predicate (gpointer object,
- QofParam *getter,
- QofQueryPredData *pd)
-{
- query_string_t pdata = (query_string_t) pd;
- const char *s;
- int ret = 0;
-
- VERIFY_PREDICATE (query_string_type);
-
- s = ((query_string_getter)getter->param_getfcn) (object, getter);
-
- if (!s) s = "";
-
- if (pdata->is_regex) {
- regmatch_t match;
- if (!regexec (&pdata->compiled, s, 1, &match, 0))
- ret = 1;
-
- } else if (pdata->options == QOF_STRING_MATCH_CASEINSENSITIVE) {
- if (strcasestr (s, pdata->matchstring))
- ret = 1;
-
- } else {
- if (strstr (s, pdata->matchstring))
- ret = 1;
- }
-
- switch (pd->how) {
- case QOF_COMPARE_EQUAL:
- return ret;
- case QOF_COMPARE_NEQ:
- return !ret;
- default:
- PWARN ("bad match type: %d", pd->how);
- return 0;
- }
-}
-
-static int
-string_compare_func (gpointer a, gpointer b, gint options,
- QofParam *getter)
-{
- const char *s1, *s2;
- g_return_val_if_fail (a && b && getter &&getter->param_getfcn, COMPARE_ERROR);
-
- s1 = ((query_string_getter)getter->param_getfcn) (a, getter);
- s2 = ((query_string_getter)getter->param_getfcn) (b, getter);
-
- if (options == QOF_STRING_MATCH_CASEINSENSITIVE)
- return safe_strcasecmp (s1, s2);
-
- return safe_strcmp (s1, s2);
-}
-
-static void
-string_free_pdata (QofQueryPredData *pd)
-{
- query_string_t pdata = (query_string_t) pd;
-
- VERIFY_PDATA (query_string_type);
-
- if (pdata->is_regex)
- regfree (&pdata->compiled);
- else
- g_free (pdata->matchstring);
-
- g_free (pdata);
-}
-
-static QofQueryPredData *
-string_copy_predicate (QofQueryPredData *pd)
-{
- query_string_t pdata = (query_string_t) pd;
-
- VERIFY_PDATA_R (query_string_type);
-
- return qof_query_string_predicate (pd->how, pdata->matchstring,
- pdata->options,
- pdata->is_regex);
-}
-
-static gboolean
-string_predicate_equal (QofQueryPredData *p1, QofQueryPredData *p2)
-{
- query_string_t pd1 = (query_string_t) p1;
- query_string_t pd2 = (query_string_t) p2;
-
- if (pd1->options != pd2->options) return FALSE;
- if (pd1->is_regex != pd2->is_regex) return FALSE;
- return (safe_strcmp (pd1->matchstring, pd2->matchstring) == 0);
-}
-
-QofQueryPredData *
-qof_query_string_predicate (QofQueryCompare how,
- const char *str, QofStringMatch options,
- gboolean is_regex)
-{
- query_string_t pdata;
-
- g_return_val_if_fail (str, NULL);
- g_return_val_if_fail (*str != '\0', NULL);
- g_return_val_if_fail (how == QOF_COMPARE_EQUAL || how == QOF_COMPARE_NEQ, NULL);
-
- pdata = g_new0 (query_string_def, 1);
- pdata->pd.type_name = query_string_type;
- pdata->pd.how = how;
- pdata->options = options;
- pdata->matchstring = g_strdup (str);
-
- if (is_regex) {
- int flags = REG_EXTENDED;
- if (options == QOF_STRING_MATCH_CASEINSENSITIVE)
- flags |= REG_ICASE;
-
- regcomp(&pdata->compiled, str, flags);
- pdata->is_regex = TRUE;
- }
-
- return ((QofQueryPredData*)pdata);
-}
-
-static char *
-string_to_string (gpointer object, QofParam *getter)
-{
- const char *res;
- res = ((query_string_getter)getter->param_getfcn)(object, getter);
- if (res)
- return g_strdup (res);
- return NULL;
-}
-
-/* QOF_TYPE_DATE =================================================== */
-
-static int
-date_compare (Timespec ta, Timespec tb, QofDateMatch options)
-{
-
- if (options == QOF_DATE_MATCH_DAY) {
- ta = timespecCanonicalDayTime (ta);
- tb = timespecCanonicalDayTime (tb);
- }
-
- if (ta.tv_sec < tb.tv_sec)
- return -1;
- if (ta.tv_sec > tb.tv_sec)
- return 1;
-
- if (ta.tv_nsec < tb.tv_nsec)
- return -1;
- if (ta.tv_nsec > tb.tv_nsec)
- return 1;
-
- return 0;
-}
-
-static int
-date_match_predicate (gpointer object, QofParam *getter,
- QofQueryPredData *pd)
-{
- query_date_t pdata = (query_date_t)pd;
- Timespec objtime;
- int compare;
-
- VERIFY_PREDICATE (query_date_type);
-
- objtime = ((query_date_getter)getter->param_getfcn) (object, getter);
- compare = date_compare (objtime, pdata->date, pdata->options);
-
- switch (pd->how) {
- case QOF_COMPARE_LT:
- return (compare < 0);
- case QOF_COMPARE_LTE:
- return (compare <= 0);
- case QOF_COMPARE_EQUAL:
- return (compare == 0);
- case QOF_COMPARE_GT:
- return (compare > 0);
- case QOF_COMPARE_GTE:
- return (compare >= 0);
- case QOF_COMPARE_NEQ:
- return (compare != 0);
- default:
- PWARN ("bad match type: %d", pd->how);
- return 0;
- }
-}
-
-static int
-date_compare_func (gpointer a, gpointer b, gint options, QofParam *getter)
-{
- Timespec ta, tb;
-
- g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
-
- ta = ((query_date_getter)getter->param_getfcn) (a, getter);
- tb = ((query_date_getter)getter->param_getfcn) (b, getter);
-
- return date_compare (ta, tb, options);
-}
-
-static void
-date_free_pdata (QofQueryPredData *pd)
-{
- query_date_t pdata = (query_date_t)pd;
-
- VERIFY_PDATA (query_date_type);
-
- g_free (pdata);
-}
-
-static QofQueryPredData *
-date_copy_predicate (QofQueryPredData *pd)
-{
- query_date_t pdata = (query_date_t)pd;
-
- VERIFY_PDATA_R (query_date_type);
-
- return qof_query_date_predicate (pd->how, pdata->options, pdata->date);
-}
-
-static gboolean
-date_predicate_equal (QofQueryPredData *p1, QofQueryPredData *p2)
-{
- query_date_t pd1 = (query_date_t) p1;
- query_date_t pd2 = (query_date_t) p2;
-
- if (pd1->options != pd2->options) return FALSE;
- return timespec_equal (&(pd1->date), &(pd2->date));
-}
-
-QofQueryPredData *
-qof_query_date_predicate (QofQueryCompare how,
- QofDateMatch options, Timespec date)
-{
- query_date_t pdata;
-
- pdata = g_new0 (query_date_def, 1);
- pdata->pd.type_name = query_date_type;
- pdata->pd.how = how;
- pdata->options = options;
- pdata->date = date;
- return ((QofQueryPredData*)pdata);
-}
-
-gboolean
-qof_query_date_predicate_get_date (QofQueryPredData *pd, Timespec *date)
-{
- query_date_t pdata = (query_date_t)pd;
-
- if (pdata->pd.type_name != query_date_type)
- return FALSE;
- *date = pdata->date;
- return TRUE;
-}
-
-static char *
-date_to_string (gpointer object, QofParam *getter)
-{
- Timespec ts = ((query_date_getter)getter->param_getfcn)(object, getter);
-
- if (ts.tv_sec || ts.tv_nsec)
- return g_strdup (gnc_print_date (ts));
-
- return NULL;
-}
-
-/* QOF_TYPE_NUMERIC ================================================= */
-
-static int
-numeric_match_predicate (gpointer object, QofParam *getter,
- QofQueryPredData* pd)
-{
- query_numeric_t pdata = (query_numeric_t)pd;
- gnc_numeric obj_val;
- int compare;
-
- VERIFY_PREDICATE (query_numeric_type);
-
- obj_val = ((query_numeric_getter)getter->param_getfcn) (object, getter);
-
- switch (pdata->options) {
- case QOF_NUMERIC_MATCH_CREDIT:
- if (gnc_numeric_positive_p (obj_val)) return 0;
- break;
- case QOF_NUMERIC_MATCH_DEBIT:
- if (gnc_numeric_negative_p (obj_val)) return 0;
- break;
- default:
- break;
- }
-
- /* Amounts are considered to be 'equal' if they match to
- * four decimal places. (epsilon=1/10000) */
- if (pd->how == QOF_COMPARE_EQUAL || pd->how == QOF_COMPARE_NEQ) {
- gnc_numeric cmp_val = gnc_numeric_create (1, 10000);
- compare =
- (gnc_numeric_compare (gnc_numeric_abs
- (gnc_numeric_sub (gnc_numeric_abs (obj_val),
- gnc_numeric_abs (pdata->amount),
- 100000, GNC_HOW_RND_ROUND)),
- cmp_val) < 0);
- } else
- compare = gnc_numeric_compare (gnc_numeric_abs (obj_val), pdata->amount);
-
- switch (pd->how) {
- case QOF_COMPARE_LT:
- return (compare < 0);
- case QOF_COMPARE_LTE:
- return (compare <= 0);
- case QOF_COMPARE_EQUAL:
- return compare;
- case QOF_COMPARE_GT:
- return (compare > 0);
- case QOF_COMPARE_GTE:
- return (compare >= 0);
- case QOF_COMPARE_NEQ:
- return !compare;
- default:
- PWARN ("bad match type: %d", pd->how);
- return 0;
- }
-}
-
-static int
-numeric_compare_func (gpointer a, gpointer b, gint options, QofParam *getter)
-{
- gnc_numeric va, vb;
-
- g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
-
- va = ((query_numeric_getter)getter->param_getfcn) (a, getter);
- vb = ((query_numeric_getter)getter->param_getfcn) (b, getter);
-
- return gnc_numeric_compare (va, vb);
-}
-
-static void
-numeric_free_pdata (QofQueryPredData* pd)
-{
- query_numeric_t pdata = (query_numeric_t)pd;
- VERIFY_PDATA (query_numeric_type);
- g_free (pdata);
-}
-
-static QofQueryPredData *
-numeric_copy_predicate (QofQueryPredData *pd)
-{
- query_numeric_t pdata = (query_numeric_t)pd;
- VERIFY_PDATA_R (query_numeric_type);
- return qof_query_numeric_predicate (pd->how, pdata->options, pdata->amount);
-}
-
-static gboolean
-numeric_predicate_equal (QofQueryPredData *p1, QofQueryPredData *p2)
-{
- query_numeric_t pd1 = (query_numeric_t) p1;
- query_numeric_t pd2 = (query_numeric_t) p2;
-
- if (pd1->options != pd2->options) return FALSE;
- return gnc_numeric_equal (pd1->amount, pd2->amount);
-}
-
-QofQueryPredData *
-qof_query_numeric_predicate (QofQueryCompare how,
- QofNumericMatch options,
- gnc_numeric value)
-{
- query_numeric_t pdata;
- pdata = g_new0 (query_numeric_def, 1);
- pdata->pd.type_name = query_numeric_type;
- pdata->pd.how = how;
- pdata->options = options;
- pdata->amount = value;
- return ((QofQueryPredData*)pdata);
-}
-
-static char *
-numeric_to_string (gpointer object, QofParam *getter)
-{
- gnc_numeric num;
- num = ((query_numeric_getter)getter->param_getfcn)(object, getter);
-
- return gnc_numeric_to_string (num);
-}
-
-static char *
-debcred_to_string (gpointer object, QofParam *getter)
-{
- gnc_numeric num;
- num = ((query_numeric_getter)getter->param_getfcn)(object, getter);
-
- return gnc_numeric_to_string (num);
-}
-
-/* QOF_TYPE_GUID =================================================== */
-
-static int
-guid_match_predicate (gpointer object, QofParam *getter,
- QofQueryPredData *pd)
-{
- query_guid_t pdata = (query_guid_t)pd;
- GList *node, *o_list;
- const GUID *guid = NULL;
-
- VERIFY_PREDICATE (query_guid_type);
-
- switch (pdata->options) {
-
- case QOF_GUID_MATCH_ALL:
- /* object is a GList of objects; param_getfcn must be called on each one.
- * See if every guid in the predicate is accounted-for in the
- * object list
- */
-
- for (node = pdata->guids; node; node = node->next)
- {
- /* See if this GUID matches the object's guid */
- for (o_list = object; o_list; o_list = o_list->next)
- {
- guid = ((query_guid_getter)getter->param_getfcn) (o_list->data, getter);
- if (guid_equal (node->data, guid))
- break;
- }
-
- /*
- * If o_list is NULL, we've walked the whole list without finding
- * a match. Therefore break out now, the match has failed.
- */
- if (o_list == NULL)
- break;
- }
-
- /*
- * The match is complete. If node == NULL then we've succesfully
- * found a match for all the guids in the predicate. Return
- * appropriately below.
- */
-
- break;
-
- case QOF_GUID_MATCH_LIST_ANY:
- /* object is a single object, getter returns a GList* of GUID*
- *
- * See if any GUID* in the returned list matches any guid in the
- * predicate match list.
- */
-
- o_list = ((query_glist_getter)getter->param_getfcn) (object, getter);
-
- for (node = o_list; node; node = node->next)
- {
- GList *node2;
-
- /* Search the predicate data for a match */
- for (node2 = pdata->guids; node2; node2 = node2->next)
- {
- if (guid_equal (node->data, node2->data))
- break;
- }
-
- /* Check to see if we found a match. If so, break now */
- if (node2 != NULL)
- break;
- }
-
- g_list_free(o_list);
-
- /* yea, node may point to an invalid location, but that's ok.
- * we're not _USING_ the value, just checking that it's non-NULL
- */
-
- break;
-
- default:
- /* object is a single object, getter returns a GUID*
- *
- * See if the guid is in the list
- */
-
- guid = ((query_guid_getter)getter->param_getfcn) (object, getter);
- for (node = pdata->guids; node; node = node->next)
- {
- if (guid_equal (node->data, guid))
- break;
- }
- }
-
- switch (pdata->options) {
- case QOF_GUID_MATCH_ANY:
- case QOF_GUID_MATCH_LIST_ANY:
- return (node != NULL);
- break;
- case QOF_GUID_MATCH_NONE:
- case QOF_GUID_MATCH_ALL:
- return (node == NULL);
- break;
- case QOF_GUID_MATCH_NULL:
- return (guid == NULL);
- break;
- default:
- PWARN ("bad match type");
- return 0;
- }
-}
-
-static void
-guid_free_pdata (QofQueryPredData *pd)
-{
- query_guid_t pdata = (query_guid_t)pd;
- GList *node;
- VERIFY_PDATA (query_guid_type);
- for (node = pdata->guids; node; node = node->next)
- {
- guid_free (node->data);
- }
- g_list_free (pdata->guids);
- g_free (pdata);
-}
-
-static QofQueryPredData *
-guid_copy_predicate (QofQueryPredData *pd)
-{
- query_guid_t pdata = (query_guid_t)pd;
- VERIFY_PDATA_R (query_guid_type);
- return qof_query_guid_predicate (pdata->options, pdata->guids);
-}
-
-static gboolean
-guid_predicate_equal (QofQueryPredData *p1, QofQueryPredData *p2)
-{
- query_guid_t pd1 = (query_guid_t) p1;
- query_guid_t pd2 = (query_guid_t) p2;
- GList *l1 = pd1->guids, *l2 = pd2->guids;
-
- if (pd1->options != pd2->options) return FALSE;
- if (g_list_length (l1) != g_list_length (l2)) return FALSE;
- for ( ; l1 ; l1 = l1->next, l2 = l2->next)
- {
- if (!guid_equal (l1->data, l2->data))
- return FALSE;
- }
- return TRUE;
-}
-
-QofQueryPredData *
-qof_query_guid_predicate (QofGuidMatch options, GList *guid_list)
-{
- query_guid_t pdata;
- GList *node;
-
- if (NULL == guid_list) return NULL;
-
- pdata = g_new0 (query_guid_def, 1);
- pdata->pd.how = QOF_COMPARE_EQUAL;
- pdata->pd.type_name = query_guid_type;
- pdata->options = options;
-
- pdata->guids = g_list_copy (guid_list);
- for (node = pdata->guids; node; node = node->next)
- {
- GUID *guid = guid_malloc ();
- *guid = *((GUID *)node->data);
- node->data = guid;
- }
- return ((QofQueryPredData*)pdata);
-}
-
-/* ================================================================ */
-/* QOF_TYPE_INT32 */
-
-static int
-int32_match_predicate (gpointer object, QofParam *getter,
- QofQueryPredData *pd)
-{
- gint32 val;
- query_int32_t pdata = (query_int32_t)pd;
-
- VERIFY_PREDICATE (query_int32_type);
-
- val = ((query_int32_getter)getter->param_getfcn) (object, getter);
-
- switch (pd->how) {
- case QOF_COMPARE_LT:
- return (val < pdata->val);
- case QOF_COMPARE_LTE:
- return (val <= pdata->val);
- case QOF_COMPARE_EQUAL:
- return (val == pdata->val);
- case QOF_COMPARE_GT:
- return (val > pdata->val);
- case QOF_COMPARE_GTE:
- return (val >= pdata->val);
- case QOF_COMPARE_NEQ:
- return (val != pdata->val);
- default:
- PWARN ("bad match type: %d", pd->how);
- return 0;
- }
-}
-
-static int
-int32_compare_func (gpointer a, gpointer b, gint options,
- QofParam *getter)
-{
- gint32 v1, v2;
- g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
-
- v1 = ((query_int32_getter)getter->param_getfcn)(a, getter);
- v2 = ((query_int32_getter)getter->param_getfcn)(b, getter);
-
- if (v1 < v2) return -1;
- if (v1 > v2) return 1;
- return 0;
-}
-
-static void
-int32_free_pdata (QofQueryPredData *pd)
-{
- query_int32_t pdata = (query_int32_t)pd;
- VERIFY_PDATA (query_int32_type);
- g_free (pdata);
-}
-
-static QofQueryPredData *
-int32_copy_predicate (QofQueryPredData *pd)
-{
- query_int32_t pdata = (query_int32_t)pd;
- VERIFY_PDATA_R (query_int32_type);
- return qof_query_int32_predicate (pd->how, pdata->val);
-}
-
-static gboolean
-int32_predicate_equal (QofQueryPredData *p1, QofQueryPredData *p2)
-{
- query_int32_t pd1 = (query_int32_t) p1;
- query_int32_t pd2 = (query_int32_t) p2;
-
- return (pd1->val == pd2->val);
-}
-
-QofQueryPredData *
-qof_query_int32_predicate (QofQueryCompare how, gint32 val)
-{
- query_int32_t pdata = g_new0 (query_int32_def, 1);
- pdata->pd.type_name = query_int32_type;
- pdata->pd.how = how;
- pdata->val = val;
- return ((QofQueryPredData*)pdata);
-}
-
-static char *
-int32_to_string (gpointer object, QofParam *getter)
-{
- gint32 num = ((query_int32_getter)getter->param_getfcn)(object, getter);
-
- return g_strdup_printf ("%d", num);
-}
-
-/* ================================================================ */
-/* QOF_TYPE_INT64 */
-
-static int
-int64_match_predicate (gpointer object, QofParam *getter,
- QofQueryPredData *pd)
-{
- gint64 val;
- query_int64_t pdata = (query_int64_t)pd;
-
- VERIFY_PREDICATE (query_int64_type);
-
- val = ((query_int64_getter)getter->param_getfcn) (object, getter);
-
- switch (pd->how) {
- case QOF_COMPARE_LT:
- return (val < pdata->val);
- case QOF_COMPARE_LTE:
- return (val <= pdata->val);
- case QOF_COMPARE_EQUAL:
- return (val == pdata->val);
- case QOF_COMPARE_GT:
- return (val > pdata->val);
- case QOF_COMPARE_GTE:
- return (val >= pdata->val);
- case QOF_COMPARE_NEQ:
- return (val != pdata->val);
- default:
- PWARN ("bad match type: %d", pd->how);
- return 0;
- }
-}
-
-static int
-int64_compare_func (gpointer a, gpointer b, gint options,
- QofParam *getter)
-{
- gint64 v1, v2;
- g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
-
- v1 = ((query_int64_getter)getter->param_getfcn)(a, getter);
- v2 = ((query_int64_getter)getter->param_getfcn)(b, getter);
-
- if (v1 < v2) return -1;
- if (v1 > v2) return 1;
- return 0;
-}
-
-static void
-int64_free_pdata (QofQueryPredData *pd)
-{
- query_int64_t pdata = (query_int64_t)pd;
- VERIFY_PDATA (query_int64_type);
- g_free (pdata);
-}
-
-static QofQueryPredData *
-int64_copy_predicate (QofQueryPredData *pd)
-{
- query_int64_t pdata = (query_int64_t)pd;
- VERIFY_PDATA_R (query_int64_type);
- return qof_query_int64_predicate (pd->how, pdata->val);
-}
-
-static gboolean
-int64_predicate_equal (QofQueryPredData *p1, QofQueryPredData *p2)
-{
- query_int64_t pd1 = (query_int64_t) p1;
- query_int64_t pd2 = (query_int64_t) p2;
-
- return (pd1->val == pd2->val);
-}
-
-QofQueryPredData *
-qof_query_int64_predicate (QofQueryCompare how, gint64 val)
-{
- query_int64_t pdata = g_new0 (query_int64_def, 1);
- pdata->pd.type_name = query_int64_type;
- pdata->pd.how = how;
- pdata->val = val;
- return ((QofQueryPredData*)pdata);
-}
-
-static char *
-int64_to_string (gpointer object, QofParam *getter)
-{
- gint64 num = ((query_int64_getter)getter->param_getfcn)(object, getter);
-
- return g_strdup_printf ("%" G_GINT64_FORMAT, num);
-}
-
-/* ================================================================ */
-/* QOF_TYPE_DOUBLE */
-
-static int
-double_match_predicate (gpointer object, QofParam *getter,
- QofQueryPredData *pd)
-{
- double val;
- query_double_t pdata = (query_double_t)pd;
-
- VERIFY_PREDICATE (query_double_type);
-
- val = ((query_double_getter)getter->param_getfcn) (object, getter);
-
- switch (pd->how) {
- case QOF_COMPARE_LT:
- return (val < pdata->val);
- case QOF_COMPARE_LTE:
- return (val <= pdata->val);
- case QOF_COMPARE_EQUAL:
- return (val == pdata->val);
- case QOF_COMPARE_GT:
- return (val > pdata->val);
- case QOF_COMPARE_GTE:
- return (val >= pdata->val);
- case QOF_COMPARE_NEQ:
- return (val != pdata->val);
- default:
- PWARN ("bad match type: %d", pd->how);
- return 0;
- }
-}
-
-static int
-double_compare_func (gpointer a, gpointer b, gint options,
- QofParam *getter)
-{
- double v1, v2;
- g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
-
- v1 = ((query_double_getter)getter->param_getfcn) (a, getter);
- v2 = ((query_double_getter)getter->param_getfcn) (b, getter);
-
- if (v1 < v2) return -1;
- if (v1 > v2) return 1;
- return 0;
-}
-
-static void
-double_free_pdata (QofQueryPredData *pd)
-{
- query_double_t pdata = (query_double_t)pd;
- VERIFY_PDATA (query_double_type);
- g_free (pdata);
-}
-
-static QofQueryPredData *
-double_copy_predicate (QofQueryPredData *pd)
-{
- query_double_t pdata = (query_double_t)pd;
- VERIFY_PDATA_R (query_double_type);
- return qof_query_double_predicate (pd->how, pdata->val);
-}
-
-static gboolean
-double_predicate_equal (QofQueryPredData *p1, QofQueryPredData *p2)
-{
- query_double_t pd1 = (query_double_t) p1;
- query_double_t pd2 = (query_double_t) p2;
-
- return (pd1->val == pd2->val);
-}
-
-QofQueryPredData *
-qof_query_double_predicate (QofQueryCompare how, double val)
-{
- query_double_t pdata = g_new0 (query_double_def, 1);
- pdata->pd.type_name = query_double_type;
- pdata->pd.how = how;
- pdata->val = val;
- return ((QofQueryPredData*)pdata);
-}
-
-static char *
-double_to_string (gpointer object, QofParam *getter)
-{
- double num = ((query_double_getter)getter->param_getfcn)(object, getter);
-
- return g_strdup_printf ("%f", num);
-}
-
-/* QOF_TYPE_BOOLEAN =================================================== */
-
-static int
-boolean_match_predicate (gpointer object, QofParam *getter,
- QofQueryPredData *pd)
-{
- gboolean val;
- query_boolean_t pdata = (query_boolean_t)pd;
-
- VERIFY_PREDICATE (query_boolean_type);
-
- val = ((query_boolean_getter)getter->param_getfcn) (object, getter);
-
- switch (pd->how) {
- case QOF_COMPARE_EQUAL:
- return (val == pdata->val);
- case QOF_COMPARE_NEQ:
- return (val != pdata->val);
- default:
- PWARN ("bad match type: %d", pd->how);
- return 0;
- }
-}
-
-static int
-boolean_compare_func (gpointer a, gpointer b, gint options,
- QofParam *getter)
-{
- gboolean va, vb;
- g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
- va = ((query_boolean_getter)getter->param_getfcn) (a, getter);
- vb = ((query_boolean_getter)getter->param_getfcn) (b, getter);
- if (!va && vb) return -1;
- if (va && !vb) return 1;
- return 0;
-}
-
-static void
-boolean_free_pdata (QofQueryPredData *pd)
-{
- query_boolean_t pdata = (query_boolean_t)pd;
- VERIFY_PDATA (query_boolean_type);
- g_free (pdata);
-}
-
-static QofQueryPredData *
-boolean_copy_predicate (QofQueryPredData *pd)
-{
- query_boolean_t pdata = (query_boolean_t)pd;
- VERIFY_PDATA_R (query_boolean_type);
- return qof_query_boolean_predicate (pd->how, pdata->val);
-}
-
-static gboolean
-boolean_predicate_equal (QofQueryPredData *p1, QofQueryPredData *p2)
-{
- query_boolean_t pd1 = (query_boolean_t) p1;
- query_boolean_t pd2 = (query_boolean_t) p2;
-
- return (pd1->val == pd2->val);
-}
-
-QofQueryPredData *
-qof_query_boolean_predicate (QofQueryCompare how, gboolean val)
-{
- query_boolean_t pdata;
- g_return_val_if_fail (how == QOF_COMPARE_EQUAL || how == QOF_COMPARE_NEQ, NULL);
-
- pdata = g_new0 (query_boolean_def, 1);
- pdata->pd.type_name = query_boolean_type;
- pdata->pd.how = how;
- pdata->val = val;
- return ((QofQueryPredData*)pdata);
-}
-
-static char *
-boolean_to_string (gpointer object, QofParam *getter)
-{
- gboolean num = ((query_boolean_getter)getter->param_getfcn)(object, getter);
-
- return g_strdup_printf ("%s", (num ? "X" : ""));
-}
-
-/* QOF_TYPE_CHAR =================================================== */
-
-static int
-char_match_predicate (gpointer object, QofParam *getter,
- QofQueryPredData *pd)
-{
- char c;
- query_char_t pdata = (query_char_t)pd;
-
- VERIFY_PREDICATE (query_char_type);
-
- c = ((query_char_getter)getter->param_getfcn) (object, getter);
-
- switch (pdata->options) {
- case QOF_CHAR_MATCH_ANY:
- if (strchr (pdata->char_list, c)) return 1;
- return 0;
- case QOF_CHAR_MATCH_NONE:
- if (!strchr (pdata->char_list, c)) return 1;
- return 0;
- default:
- PWARN ("bad match type");
- return 0;
- }
-}
-
-static int
-char_compare_func (gpointer a, gpointer b, gint options, QofParam *getter)
-{
- char va, vb;
- g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
- va = ((query_char_getter)getter->param_getfcn)(a, getter);
- vb = ((query_char_getter)getter->param_getfcn)(b, getter);
- return (va-vb);
-}
-
-static void
-char_free_pdata (QofQueryPredData *pd)
-{
- query_char_t pdata = (query_char_t)pd;
- VERIFY_PDATA (query_char_type);
- g_free (pdata->char_list);
- g_free (pdata);
-}
-
-static QofQueryPredData *
-char_copy_predicate (QofQueryPredData *pd)
-{
- query_char_t pdata = (query_char_t)pd;
- VERIFY_PDATA_R (query_char_type);
- return qof_query_char_predicate (pdata->options, pdata->char_list);
-}
-
-static gboolean
-char_predicate_equal (QofQueryPredData *p1, QofQueryPredData *p2)
-{
- query_char_t pd1 = (query_char_t) p1;
- query_char_t pd2 = (query_char_t) p2;
-
- if (pd1->options != pd2->options) return FALSE;
- return (safe_strcmp (pd1->char_list, pd2->char_list) == 0);
-}
-
-QofQueryPredData *
-qof_query_char_predicate (QofCharMatch options, const char *chars)
-{
- query_char_t pdata;
- g_return_val_if_fail (chars, NULL);
- pdata = g_new0 (query_char_def, 1);
- pdata->pd.type_name = query_char_type;
- pdata->pd.how = QOF_COMPARE_EQUAL;
- pdata->options = options;
- pdata->char_list = g_strdup (chars);
- return ((QofQueryPredData*)pdata);
-}
-
-static char *
-char_to_string (gpointer object, QofParam *getter)
-{
- char num = ((query_char_getter)getter->param_getfcn)(object, getter);
-
- return g_strdup_printf ("%c", num);
-}
-
-/* QOF_TYPE_KVP ================================================ */
-
-static int
-kvp_match_predicate (gpointer object, QofParam *getter,
- QofQueryPredData *pd)
-{
- int compare;
- KvpFrame *kvp;
- KvpValue *value;
- query_kvp_t pdata = (query_kvp_t)pd;
-
- VERIFY_PREDICATE (query_kvp_type);
-
- kvp = ((query_kvp_getter)getter->param_getfcn) (object, getter);
- if (!kvp)
- return 0;
-
- value = kvp_frame_get_slot_path_gslist (kvp, pdata->path);
- if (!value)
- return 0;
-
- if (kvp_value_get_type (value) != kvp_value_get_type (pdata->value))
- return 0;
-
- compare = kvp_value_compare (value, pdata->value);
-
- switch (pd->how)
- {
- case QOF_COMPARE_LT:
- return (compare < 0);
- case QOF_COMPARE_LTE:
- return (compare <= 0);
- case QOF_COMPARE_EQUAL:
- return (compare == 0);
- case QOF_COMPARE_GTE:
- return (compare >= 0);
- case QOF_COMPARE_GT:
- return (compare > 0);
- case QOF_COMPARE_NEQ:
- return (compare != 0);
- default:
- PWARN ("bad match type: %d", pd->how);
- return 0;
- }
-}
-
-static void
-kvp_free_pdata (QofQueryPredData *pd)
-{
- query_kvp_t pdata = (query_kvp_t)pd;
- GSList *node;
-
- VERIFY_PDATA (query_kvp_type);
- kvp_value_delete (pdata->value);
- for (node = pdata->path; node; node = node->next)
- {
- g_free (node->data);
- node->data = NULL;
- }
- g_slist_free (pdata->path);
- g_free (pdata);
-}
-
-static QofQueryPredData *
-kvp_copy_predicate (QofQueryPredData *pd)
-{
- query_kvp_t pdata = (query_kvp_t)pd;
- VERIFY_PDATA_R (query_kvp_type);
- return qof_query_kvp_predicate (pd->how, pdata->path, pdata->value);
-}
-
-static gboolean
-kvp_predicate_equal (QofQueryPredData *p1, QofQueryPredData *p2)
-{
- query_kvp_t pd1 = (query_kvp_t) p1;
- query_kvp_t pd2 = (query_kvp_t) p2;
- GSList *n1, *n2;
-
- n1 = pd1->path;
- n2 = pd2->path;
-
- for ( ; n1 && n2; n1 = n1->next, n2 = n2->next)
- {
- if (safe_strcmp (n1->data, n2->data) != 0)
- return FALSE;
- }
-
- if (n1 || n2)
- return FALSE;
-
- return (kvp_value_compare (pd1->value, pd2->value) == 0);
-}
-
-QofQueryPredData *
-qof_query_kvp_predicate (QofQueryCompare how,
- GSList *path, const KvpValue *value)
-{
- query_kvp_t pdata;
- GSList *node;
-
- g_return_val_if_fail (path && value, NULL);
-
- pdata = g_new0 (query_kvp_def, 1);
- pdata->pd.type_name = query_kvp_type;
- pdata->pd.how = how;
- pdata->value = kvp_value_copy (value);
- pdata->path = g_slist_copy (path);
- for (node = pdata->path; node; node = node->next)
- node->data = g_strdup (node->data);
-
- return ((QofQueryPredData*)pdata);
-}
-
-QofQueryPredData *
-qof_query_kvp_predicate_path (QofQueryCompare how,
- const char *path, const KvpValue *value)
-{
- QofQueryPredData *pd;
- GSList *spath = NULL;
- char *str, *p;
-
- if (!path) return NULL;
-
- str = g_strdup (path);
- p = str;
- if (0 == *p) return NULL;
- if ('/' == *p) p++;
-
- while (p)
- {
- spath = g_slist_append (spath, p);
- p = strchr (p, '/');
- if (p) { *p = 0; p++; }
- }
-
- pd = qof_query_kvp_predicate (how, spath, value);
- g_free (str);
- return pd;
-}
-
-
-/* QOF_TYPE_COLLECT =============================================== */
-
-static int
-collect_match_predicate (gpointer object, QofParam *getter,
- QofQueryPredData *pd)
-{
- query_coll_t pdata;
- QofCollection *coll;
- GList *node, *node2, *o_list;
- const GUID *guid;
-
- pdata = (query_coll_t)pd;
- VERIFY_PREDICATE (query_collect_type);
- coll = ((query_collect_getter)getter->param_getfcn) (object, getter);
- guid = NULL;
- switch(pdata->options) {
- case QOF_GUID_MATCH_ALL : {
- for (node = pdata->guids; node; node = node->next)
- {
- for (o_list = object; o_list; o_list = o_list->next)
- {
- guid = ((query_guid_getter)getter->param_getfcn)
- (o_list->data, getter);
- if (guid_equal (node->data, guid)) {
- break;
- }
- }
- if (o_list == NULL) {
- break;
- }
- }
- break;
- }
- case QOF_GUID_MATCH_LIST_ANY : {
- o_list = ((query_glist_getter)getter->param_getfcn) (object, getter);
- for (node = o_list; node; node = node->next)
- {
- for (node2 = pdata->guids; node2; node2 = node2->next)
- {
- if (guid_equal (node->data, node2->data)) {
- break;
- }
- }
- if (node2 != NULL) {
- break;
- }
- }
- g_list_free(o_list);
- break;
- }
- default : {
- guid = ((query_guid_getter)getter->param_getfcn) (object, getter);
- for (node = pdata->guids; node; node = node->next)
- {
- if (guid_equal (node->data, guid)) {
- break;
- }
- }
- }
- switch (pdata->options) {
- case QOF_GUID_MATCH_ANY :
- case QOF_GUID_MATCH_LIST_ANY : {
- return (node != NULL);
- break;
- }
- case QOF_GUID_MATCH_NONE :
- case QOF_GUID_MATCH_ALL : {
- return (node == NULL);
- break;
- }
- case QOF_GUID_MATCH_NULL : {
- return (guid == NULL);
- break;
- }
- default : {
- PWARN ("bad match type");
- return 0;
- }
- }
- }
- return 0;
-}
-
-static int
-collect_compare_func (gpointer a, gpointer b, gint options, QofParam *getter)
-{
- gint result;
- QofCollection *c1, *c2;
-
- c1 = ((query_collect_getter)getter->param_getfcn) (a, getter);
- c2 = ((query_collect_getter)getter->param_getfcn) (b, getter);
- result = qof_collection_compare(c1, c2);
- return result;
-}
-
-static void
-collect_free_pdata (QofQueryPredData *pd)
-{
- query_coll_t pdata;
- GList *node;
-
- node = NULL;
- pdata = (query_coll_t) pd;
- VERIFY_PDATA (query_collect_type);
- for (node = pdata->guids; node; node = node->next)
- {
- guid_free (node->data);
- }
- qof_collection_destroy(pdata->coll);
- g_list_free (pdata->guids);
- g_free (pdata);
-}
-
-static QofQueryPredData *
-collect_copy_predicate (QofQueryPredData *pd)
-{
- query_coll_t pdata = (query_coll_t) pd;
-
- VERIFY_PDATA_R (query_collect_type);
- return qof_query_collect_predicate (pdata->options, pdata->coll);
-}
-
-static gboolean
-collect_predicate_equal (QofQueryPredData *p1, QofQueryPredData *p2)
-{
- query_coll_t pd1;
- query_coll_t pd2;
- gint result;
-
- pd1 = (query_coll_t) p1;
- pd2 = (query_coll_t) p2;
- result = qof_collection_compare(pd1->coll, pd2->coll);
- if(result == 0) { return TRUE; }
- return FALSE;
-}
-
-static void
-query_collect_cb(QofEntity* ent, gpointer user_data)
-{
- query_coll_t pdata;
- GUID *guid;
-
- guid = guid_malloc();
- guid = (GUID*)qof_entity_get_guid(ent);
- pdata = (query_coll_t)user_data;
- pdata->guids = g_list_append(pdata->guids, guid);
-}
-
-QofQueryPredData *
-qof_query_collect_predicate (QofGuidMatch options, QofCollection *coll)
-{
- query_coll_t pdata;
-
- g_return_val_if_fail (coll, NULL);
- pdata = g_new0 (query_coll_def, 1);
- pdata->pd.type_name = query_collect_type;
- pdata->options = options;
- qof_collection_foreach(coll, query_collect_cb, pdata);
- if (NULL == pdata->guids) { return NULL; }
- return ((QofQueryPredData*)pdata);
-}
-
-/* QOF_TYPE_CHOICE */
-
-static int
-choice_match_predicate (gpointer object, QofParam *getter,
- QofQueryPredData *pd)
-{
- query_choice_t pdata = (query_choice_t)pd;
- GList *node, *o_list;
- const GUID *guid = NULL;
-
- VERIFY_PREDICATE (query_choice_type);
-
- switch (pdata->options) {
-
- case QOF_GUID_MATCH_ALL:
- /* object is a GList of objects; param_getfcn must be called on each one.
- * See if every guid in the predicate is accounted-for in the
- * object list
- */
-
- for (node = pdata->guids; node; node = node->next)
- {
- /* See if this GUID matches the object's guid */
- for (o_list = object; o_list; o_list = o_list->next)
- {
- guid = ((query_choice_getter)getter->param_getfcn) (o_list->data, getter);
- if (guid_equal (node->data, guid))
- break;
- }
-
- /*
- * If o_list is NULL, we've walked the whole list without finding
- * a match. Therefore break out now, the match has failed.
- */
- if (o_list == NULL)
- break;
- }
-
- /*
- * The match is complete. If node == NULL then we've succesfully
- * found a match for all the guids in the predicate. Return
- * appropriately below.
- */
-
- break;
-
- case QOF_GUID_MATCH_LIST_ANY:
-
- o_list = ((query_glist_getter)getter->param_getfcn) (object, getter);
-
- for (node = o_list; node; node = node->next)
- {
- GList *node2;
-
- for (node2 = pdata->guids; node2; node2 = node2->next)
- {
- if (guid_equal (node->data, node2->data))
- break;
- }
-
- if (node2 != NULL)
- break;
- }
-
- g_list_free(o_list);
-
- break;
-
- default:
- /* object is a single object, getter returns a GUID*
- *
- * See if the guid is in the list
- */
-
- guid = ((query_choice_getter)getter->param_getfcn) (object, getter);
- for (node = pdata->guids; node; node = node->next)
- {
- if (guid_equal (node->data, guid))
- break;
- }
- }
-
- switch (pdata->options) {
- case QOF_GUID_MATCH_ANY:
- case QOF_GUID_MATCH_LIST_ANY:
- return (node != NULL);
- break;
- case QOF_GUID_MATCH_NONE:
- case QOF_GUID_MATCH_ALL:
- return (node == NULL);
- break;
- case QOF_GUID_MATCH_NULL:
- return (guid == NULL);
- break;
- default:
- PWARN ("bad match type");
- return 0;
- }
-}
-
-static void
-choice_free_pdata (QofQueryPredData *pd)
-{
- query_choice_t pdata = (query_choice_t)pd;
- GList *node;
- VERIFY_PDATA (query_choice_type);
- for (node = pdata->guids; node; node = node->next)
- {
- guid_free (node->data);
- }
- g_list_free (pdata->guids);
- g_free (pdata);
-}
-
-static QofQueryPredData *
-choice_copy_predicate (QofQueryPredData *pd)
-{
- query_choice_t pdata = (query_choice_t)pd;
- VERIFY_PDATA_R (query_choice_type);
- return qof_query_choice_predicate (pdata->options, pdata->guids);
-}
-
-static gboolean
-choice_predicate_equal (QofQueryPredData *p1, QofQueryPredData *p2)
-{
- query_choice_t pd1 = (query_choice_t) p1;
- query_choice_t pd2 = (query_choice_t) p2;
- GList *l1 = pd1->guids, *l2 = pd2->guids;
-
- if (pd1->options != pd2->options) return FALSE;
- if (g_list_length (l1) != g_list_length (l2)) return FALSE;
- for ( ; l1 ; l1 = l1->next, l2 = l2->next)
- {
- if (!guid_equal (l1->data, l2->data))
- return FALSE;
- }
- return TRUE;
-}
-
-QofQueryPredData *
-qof_query_choice_predicate (QofGuidMatch options, GList *guid_list)
-{
- query_choice_t pdata;
- GList *node;
-
- if (NULL == guid_list) return NULL;
-
- pdata = g_new0 (query_choice_def, 1);
- pdata->pd.how = QOF_COMPARE_EQUAL;
- pdata->pd.type_name = query_choice_type;
- pdata->options = options;
-
- pdata->guids = g_list_copy (guid_list);
- for (node = pdata->guids; node; node = node->next)
- {
- GUID *guid = guid_malloc ();
- *guid = *((GUID *)node->data);
- node->data = guid;
- }
- return ((QofQueryPredData*)pdata);
-}
-
-
-/* initialization ================================================== */
-/** This function registers a new Core Object with the QofQuery
- * subsystem. It maps the "core_name" object to the given
- * query_predicate, predicate_copy, and predicate_data_free functions.
- *
- * An example:
- * qof_query_register_core_object (QOF_TYPE_STRING, string_match_predicate,
- * string_compare_fcn, string_free_pdata,
- * string_print_fcn, pred_equal_fcn);
- */
-
-
-static void
-qof_query_register_core_object (QofType core_name,
- QofQueryPredicateFunc pred,
- QofCompareFunc comp,
- QueryPredicateCopyFunc copy,
- QueryPredDataFree pd_free,
- QueryToString toString,
- QueryPredicateEqual pred_equal)
-{
- g_return_if_fail (core_name);
- g_return_if_fail (*core_name != '\0');
-
- if (pred)
- g_hash_table_insert (predTable, (char *)core_name, pred);
-
- if (comp)
- g_hash_table_insert (cmpTable, (char *)core_name, comp);
-
- if (copy)
- g_hash_table_insert (copyTable, (char *)core_name, copy);
-
- if (pd_free)
- g_hash_table_insert (freeTable, (char *)core_name, pd_free);
-
- if (toString)
- g_hash_table_insert (toStringTable, (char *)core_name, toString);
-
- if (pred_equal)
- g_hash_table_insert (predEqualTable, (char *)core_name, pred_equal);
-}
-
-static void init_tables (void)
-{
- unsigned int i;
- struct
- {
- QofType name;
- QofQueryPredicateFunc pred;
- QofCompareFunc comp;
- QueryPredicateCopyFunc copy;
- QueryPredDataFree pd_free;
- QueryToString toString;
- QueryPredicateEqual pred_equal;
- } knownTypes[] =
- {
- { QOF_TYPE_STRING, string_match_predicate, string_compare_func,
- string_copy_predicate, string_free_pdata, string_to_string,
- string_predicate_equal },
- { QOF_TYPE_DATE, date_match_predicate, date_compare_func,
- date_copy_predicate, date_free_pdata, date_to_string,
- date_predicate_equal },
- { QOF_TYPE_DEBCRED, numeric_match_predicate, numeric_compare_func,
- numeric_copy_predicate, numeric_free_pdata, debcred_to_string,
- numeric_predicate_equal },
- { QOF_TYPE_NUMERIC, numeric_match_predicate, numeric_compare_func,
- numeric_copy_predicate, numeric_free_pdata, numeric_to_string,
- numeric_predicate_equal },
- { QOF_TYPE_GUID, guid_match_predicate, NULL,
- guid_copy_predicate, guid_free_pdata, NULL,
- guid_predicate_equal },
- { QOF_TYPE_INT32, int32_match_predicate, int32_compare_func,
- int32_copy_predicate, int32_free_pdata, int32_to_string,
- int32_predicate_equal },
- { QOF_TYPE_INT64, int64_match_predicate, int64_compare_func,
- int64_copy_predicate, int64_free_pdata, int64_to_string,
- int64_predicate_equal },
- { QOF_TYPE_DOUBLE, double_match_predicate, double_compare_func,
- double_copy_predicate, double_free_pdata, double_to_string,
- double_predicate_equal },
- { QOF_TYPE_BOOLEAN, boolean_match_predicate, boolean_compare_func,
- boolean_copy_predicate, boolean_free_pdata, boolean_to_string,
- boolean_predicate_equal },
- { QOF_TYPE_CHAR, char_match_predicate, char_compare_func,
- char_copy_predicate, char_free_pdata, char_to_string,
- char_predicate_equal },
- { QOF_TYPE_KVP, kvp_match_predicate, NULL, kvp_copy_predicate,
- kvp_free_pdata, NULL, kvp_predicate_equal },
- { QOF_TYPE_COLLECT, collect_match_predicate, collect_compare_func,
- collect_copy_predicate, collect_free_pdata, NULL,
- collect_predicate_equal },
- { QOF_TYPE_CHOICE, choice_match_predicate, NULL,
- choice_copy_predicate, choice_free_pdata, NULL, choice_predicate_equal },
- };
-
- /* Register the known data types */
- for (i = 0; i < (sizeof(knownTypes)/sizeof(*knownTypes)); i++)
- {
- qof_query_register_core_object (knownTypes[i].name,
- knownTypes[i].pred,
- knownTypes[i].comp,
- knownTypes[i].copy,
- knownTypes[i].pd_free,
- knownTypes[i].toString,
- knownTypes[i].pred_equal);
- }
-}
-
-static QueryPredicateCopyFunc
-qof_query_copy_predicate (QofType type)
-{
- QueryPredicateCopyFunc rc;
- g_return_val_if_fail (type, NULL);
- rc = g_hash_table_lookup (copyTable, type);
- return rc;
-}
-
-static QueryPredDataFree
-qof_query_predicate_free (QofType type)
-{
- g_return_val_if_fail (type, NULL);
- return g_hash_table_lookup (freeTable, type);
-}
-
-/********************************************************************/
-/* PUBLISHED API FUNCTIONS */
-
-void qof_query_core_init (void)
-{
- /* Only let us initialize once */
- if (initialized) return;
- initialized = TRUE;
-
- /* Create the tables */
- predTable = g_hash_table_new (g_str_hash, g_str_equal);
- cmpTable = g_hash_table_new (g_str_hash, g_str_equal);
- copyTable = g_hash_table_new (g_str_hash, g_str_equal);
- freeTable = g_hash_table_new (g_str_hash, g_str_equal);
- toStringTable = g_hash_table_new (g_str_hash, g_str_equal);
- predEqualTable = g_hash_table_new (g_str_hash, g_str_equal);
-
- init_tables ();
-}
-
-void qof_query_core_shutdown (void)
-{
- if (!initialized) return;
- initialized = FALSE;
-
- g_hash_table_destroy (predTable);
- g_hash_table_destroy (cmpTable);
- g_hash_table_destroy (copyTable);
- g_hash_table_destroy (freeTable);
- g_hash_table_destroy (toStringTable);
- g_hash_table_destroy (predEqualTable);
-}
-
-QofQueryPredicateFunc
-qof_query_core_get_predicate (QofType type)
-{
- g_return_val_if_fail (type, NULL);
- return g_hash_table_lookup (predTable, type);
-}
-
-QofCompareFunc
-qof_query_core_get_compare (QofType type)
-{
- g_return_val_if_fail (type, NULL);
- return g_hash_table_lookup (cmpTable, type);
-}
-
-void
-qof_query_core_predicate_free (QofQueryPredData *pdata)
-{
- QueryPredDataFree free_fcn;
-
- g_return_if_fail (pdata);
- g_return_if_fail (pdata->type_name);
-
- free_fcn = qof_query_predicate_free (pdata->type_name);
- free_fcn (pdata);
-}
-
-QofQueryPredData *
-qof_query_core_predicate_copy (QofQueryPredData *pdata)
-{
- QueryPredicateCopyFunc copy;
-
- g_return_val_if_fail (pdata, NULL);
- g_return_val_if_fail (pdata->type_name, NULL);
-
- copy = qof_query_copy_predicate (pdata->type_name);
- return (copy (pdata));
-}
-
-char *
-qof_query_core_to_string (QofType type, gpointer object,
- QofParam *getter)
-{
- QueryToString toString;
-
- g_return_val_if_fail (type, NULL);
- g_return_val_if_fail (object, NULL);
- g_return_val_if_fail (getter, NULL);
-
- toString = g_hash_table_lookup (toStringTable, type);
- g_return_val_if_fail (toString, NULL);
-
- return toString (object, getter);
-}
-
-gboolean
-qof_query_core_predicate_equal (QofQueryPredData *p1, QofQueryPredData *p2)
-{
- QueryPredicateEqual pred_equal;
-
- if (p1 == p2) return TRUE;
- if (!p1 || !p2) return FALSE;
-
- if (p1->how != p2->how) return FALSE;
- if (safe_strcmp (p1->type_name, p2->type_name)) return FALSE;
-
- pred_equal = g_hash_table_lookup (predEqualTable, p1->type_name);
- g_return_val_if_fail (pred_equal, FALSE);
-
- return pred_equal (p1, p2);
-}
Deleted: gnucash/trunk/src/engine/qofquerycore.h
===================================================================
--- gnucash/trunk/src/engine/qofquerycore.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofquerycore.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,196 +0,0 @@
-/********************************************************************\
- * qofquerycore.h -- API for providing core Query data types *
- * Copyright (C) 2002 Derek Atkins <warlord at MIT.EDU> *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-/** @addtogroup Query
- @{ */
-
-/** @file qofquerycore.h
- @brief API for providing core Query data types
- @author Copyright (C) 2002 Derek Atkins <warlord at MIT.EDU>
-*/
-
-#ifndef QOF_QUERYCORE_H
-#define QOF_QUERYCORE_H
-
-#include <glib.h>
-
-#include "gnc-numeric.h"
-#include "gnc-date.h"
-#include "kvp_frame.h"
-#include "qofclass.h"
-
-/**
- * PREDICATE DATA TYPES: All the predicate data types are rolled up into
- * the union type PredicateData. The "type" field specifies which type
- * the union is.
- */
-typedef struct _QofQueryPredData QofQueryPredData;
-
-/** Standard Query comparitors, for how to compare objects in a predicate.
- * Note that not all core types implement all comparitors
- */
-typedef enum {
- QOF_COMPARE_LT = 1,
- QOF_COMPARE_LTE,
- QOF_COMPARE_EQUAL,
- QOF_COMPARE_GT,
- QOF_COMPARE_GTE,
- QOF_COMPARE_NEQ
-} QofQueryCompare;
-
-/** List of known core query data-types...
- * Each core query type defines it's set of optional "comparitor qualifiers".
- */
-/* Comparisons for QOF_TYPE_STRING */
-typedef enum {
- QOF_STRING_MATCH_NORMAL = 1,
- QOF_STRING_MATCH_CASEINSENSITIVE
-} QofStringMatch;
-
-/** Comparisons for QOF_TYPE_DATE
- * The QOF_DATE_MATCH_DAY comparison rounds the two time
- * values to mid-day and then compares these rounded values.
- * The QOF_DATE_MATCH_NORMAL comparison matches the time values,
- * down to the second.
- */
-/* XXX remove these deprecated old names .. */
-//#define QOF_DATE_MATCH_ROUNDED QOF_DATE_MATCH_DAY
-//#define QOF_DATE_MATCH_NORMAL QOF_DATE_MATCH_TIME
-typedef enum {
- QOF_DATE_MATCH_NORMAL = 1,
- QOF_DATE_MATCH_DAY
-} QofDateMatch;
-
-/** Comparisons for QOF_TYPE_NUMERIC, QOF_TYPE_DEBCRED
- *
- * XXX Should be deprecated, or at least wrapped up as a convnience
- * function, this is based on the old bill gribble code, which assumed
- * the amount was always positive, and then specified a funds-flow
- * direction (credit, debit, or either).
- *
- * The point being that 'match credit' is equivalent to the compound
- * predicate (amount >= 0) && (amount 'op' value) while the 'match
- * debit' predicate is equivalent to (amount <= 0) && (abs(amount) 'op' value)
-*/
-
-typedef enum {
- QOF_NUMERIC_MATCH_DEBIT = 1,
- QOF_NUMERIC_MATCH_CREDIT,
- QOF_NUMERIC_MATCH_ANY
-} QofNumericMatch;
-
-/* Comparisons for QOF_TYPE_GUID */
-typedef enum {
- /** These expect a single object and expect the
- * QofAccessFunc returns GUID* */
- QOF_GUID_MATCH_ANY = 1,
- QOF_GUID_MATCH_NONE,
- QOF_GUID_MATCH_NULL,
- /** These expect a GList* of objects and calls the QofAccessFunc routine
- * on each item in the list to obtain a GUID* for each object */
- QOF_GUID_MATCH_ALL,
- /** These expect a single object and expect the QofAccessFunc function
- * to return a GList* of GUID* (the list is the property of the caller) */
- QOF_GUID_MATCH_LIST_ANY,
-} QofGuidMatch;
-
-/** A CHAR type is for a RECNCell, Comparisons for QOF_TYPE_CHAR
- * 'ANY' will match any charagter in the string.
- *
- * Match 'ANY' is a convenience/performance-enhanced predicate
- * for the compound statement (value==char1) || (value==char2) || etc.
- * Match 'NONE' is equivalent to
- * (value != char1) && (value != char2) && etc.
- */
-typedef enum {
- QOF_CHAR_MATCH_ANY = 1,
- QOF_CHAR_MATCH_NONE
-} QofCharMatch;
-
-/** No extended comparisons for QOF_TYPE_INT32, QOF_TYPE_INT64,
- * QOF_TYPE_DOUBLE, QOF_TYPE_BOOLEAN, QOF_TYPE_KVP
- */
-
-/** Head of Predicate Data structures. All PData must start like this. */
-struct _QofQueryPredData {
- QofType type_name; /* QOF_TYPE_* */
- QofQueryCompare how;
-};
-
-
-/** @name Core Data Type Predicates
- @{ */
-QofQueryPredData *qof_query_string_predicate (QofQueryCompare how,
- const char *str,
- QofStringMatch options,
- gboolean is_regex);
-
-QofQueryPredData *qof_query_date_predicate (QofQueryCompare how,
- QofDateMatch options,
- Timespec date);
-
-QofQueryPredData *qof_query_numeric_predicate (QofQueryCompare how,
- QofNumericMatch options,
- gnc_numeric value);
-
-QofQueryPredData *qof_query_guid_predicate (QofGuidMatch options, GList *guids);
-QofQueryPredData *qof_query_int32_predicate (QofQueryCompare how, gint32 val);
-QofQueryPredData *qof_query_int64_predicate (QofQueryCompare how, gint64 val);
-QofQueryPredData *qof_query_double_predicate (QofQueryCompare how, double val);
-QofQueryPredData *qof_query_boolean_predicate (QofQueryCompare how, gboolean val);
-QofQueryPredData *qof_query_char_predicate (QofCharMatch options,
- const char *chars);
-QofQueryPredData *qof_query_collect_predicate (QofGuidMatch options,
- QofCollection *coll);
-QofQueryPredData *qof_query_choice_predicate (QofGuidMatch options, GList *guids);
-
-/** The qof_query_kvp_predicate() matches the object that has
- * the value 'value' located at the path 'path'. In a certain
- * sense, the 'path' is handled as if it were a paramter.
- */
-QofQueryPredData *qof_query_kvp_predicate (QofQueryCompare how,
- GSList *path,
- const KvpValue *value);
-
-/** Same predicate as above, except that 'path' is assumed to be
- * a string containing slash-separated pathname. */
-QofQueryPredData *qof_query_kvp_predicate_path (QofQueryCompare how,
- const char *path,
- const KvpValue *value);
-
-/** Copy a predicate. */
-QofQueryPredData *qof_query_core_predicate_copy (QofQueryPredData *pdata);
-
-/** Destroy a predicate. */
-void qof_query_core_predicate_free (QofQueryPredData *pdata);
-
-/** Retrieve a predicate. */
-gboolean qof_query_date_predicate_get_date (QofQueryPredData *pd, Timespec *date);
-/** Return a printable string for a core data object. Caller needs
- * to g_free() the returned string.
- */
-char * qof_query_core_to_string (QofType, gpointer object, QofParam *getter);
-
-#endif /* QOF_QUERYCORE_H */
-/* @} */
-/* @} */
Deleted: gnucash/trunk/src/engine/qofsession-p.h
===================================================================
--- gnucash/trunk/src/engine/qofsession-p.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofsession-p.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,76 +0,0 @@
-/********************************************************************\
- * qofsession-p.h -- private functions for QOF sessions. *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-/*
- * HISTORY:
- * Copyright (c) 2001 Linux Developers Group
- * Copyright (c) 1998-2003 Linas Vepstas <linas at linas.org>
- */
-
-#ifndef QOF_SESSION_P_H
-#define QOF_SESSION_P_H
-
-#include "qofbook.h"
-#include "qofsession.h"
-
-struct _QofSession
-{
- /* This is just a "fake" entry point to allow me to pass a Session as
- * an Entity. NOTE: THIS IS NOT AN ENTITY! THE ONLY PART OF ENTITY
- * THAT IS VALID IS E_TYPE!
- */
- QofEntity entity;
-
- /* A book holds pointers to the various types of datasets.
- * A session may have multiple books. */
- GList *books;
-
- /* The requested book id, in the form or a URI, such as
- * file:/some/where, or sql:server.host.com:555
- */
- char *book_id;
-
- /* If any book subroutine failed, this records the failure reason
- * (file not found, etc).
- * This is a 'stack' that is one deep. (Should be deeper ??)
- * FIXME: Each backend has its own error stack. The session
- * and the backends should all be using (or making it look like)
- * there is only one stack.
- */
- QofBackendError last_err;
- char *error_message;
-
- /* ---------------------------------------------------- */
- /* Pointer to the backend that is actually used to move data
- * between the persistant store and the local engine. */
- QofBackend *backend;
-};
-
-
-QofBackend * qof_session_get_backend (QofSession *session);
-
-void qof_session_push_error (QofSession *session, QofBackendError err,
- const char *message);
-
-QofBackend* gncBackendInit_file(const char *book_id, void *data);
-
-#endif
Deleted: gnucash/trunk/src/engine/qofsession.c
===================================================================
--- gnucash/trunk/src/engine/qofsession.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofsession.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,1373 +0,0 @@
-/********************************************************************\
- * qofsesssion.c -- session access (connection to backend) *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
-\********************************************************************/
-
-/**
- * @file qofsession.c
- * @brief Encapsulate a connection to a storage backend.
- *
- * HISTORY:
- * Created by Linas Vepstas December 1998
-
- @author Copyright (c) 1998-2004 Linas Vepstas <linas at linas.org>
- @author Copyright (c) 2000 Dave Peticolas
- @author Copyright (c) 2005 Neil Williams <linux at codehelp.co.uk>
- */
-
-#include "config.h"
-
-#include <dlfcn.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <glib.h>
-#include "qofla-dir.h"
-#include "gnc-trace.h"
-#include "gnc-engine-util.h"
-#include "gnc-event.h"
-#include "qofsession.h"
-#include "qofbackend-p.h"
-#include "qof-be-utils.h"
-#include "qofbook.h"
-#include "qofbook-p.h"
-#include "qofobject.h"
-#include "qofsession-p.h"
-
-/** \deprecated should not be static */
-static QofSession * current_session = NULL;
-static GHookList * session_closed_hooks = NULL;
-static QofLogModule log_module = QOF_MOD_SESSION;
-static GSList *provider_list = NULL;
-
-/* ====================================================================== */
-
-void
-qof_backend_register_provider (QofBackendProvider *prov)
-{
- provider_list = g_slist_prepend (provider_list, prov);
-}
-
-/* ====================================================================== */
-
-/* hook routines */
-
-void
-qof_session_add_close_hook (GFunc fn, gpointer data)
-{
- GHook *hook;
-
- if (session_closed_hooks == NULL) {
- session_closed_hooks = malloc(sizeof(GHookList)); /* LEAKED */
- g_hook_list_init (session_closed_hooks, sizeof(GHook));
- }
-
- hook = g_hook_alloc(session_closed_hooks);
- if (!hook)
- return;
-
- hook->func = (GHookFunc)fn;
- hook->data = data;
- g_hook_append(session_closed_hooks, hook);
-}
-
-void
-qof_session_call_close_hooks (QofSession *session)
-{
- GHook *hook;
- GFunc fn;
-
- if (session_closed_hooks == NULL)
- return;
-
- hook = g_hook_first_valid (session_closed_hooks, FALSE);
- while (hook) {
- fn = (GFunc)hook->func;
- fn(session, hook->data);
- hook = g_hook_next_valid (session_closed_hooks, hook, FALSE);
- }
-}
-
-/* ====================================================================== */
-/* error handling routines */
-
-static void
-qof_session_clear_error (QofSession *session)
-{
- QofBackendError err;
-
- session->last_err = ERR_BACKEND_NO_ERR;
- g_free(session->error_message);
- session->error_message = NULL;
-
- /* pop the stack on the backend as well. */
- if (session->backend)
- {
- do
- {
- err = qof_backend_get_error (session->backend);
- } while (ERR_BACKEND_NO_ERR != err);
- }
-}
-
-void
-qof_session_push_error (QofSession *session, QofBackendError err,
- const char *message)
-{
- if (!session) return;
-
- g_free (session->error_message);
-
- session->last_err = err;
- session->error_message = g_strdup (message);
-}
-
-QofBackendError
-qof_session_get_error (QofSession * session)
-{
- QofBackendError err;
-
- if (!session) return ERR_BACKEND_NO_BACKEND;
-
- /* if we have a local error, return that. */
- if (ERR_BACKEND_NO_ERR != session->last_err)
- {
- return session->last_err;
- }
-
- /* maybe we should return a no-backend error ??? */
- if (! session->backend) return ERR_BACKEND_NO_ERR;
-
- err = qof_backend_get_error (session->backend);
- session->last_err = err;
- return err;
-}
-
-static const char *
-get_default_error_message(QofBackendError err)
-{
- return "";
-}
-
-const char *
-qof_session_get_error_message(QofSession *session)
-{
- if(!session) return "";
- if(!session->error_message)
- return get_default_error_message(session->last_err);
- return session->error_message;
-}
-
-QofBackendError
-qof_session_pop_error (QofSession * session)
-{
- QofBackendError err;
-
- if (!session) return ERR_BACKEND_NO_BACKEND;
-
- err = qof_session_get_error(session);
- qof_session_clear_error(session);
-
- return err;
-}
-
-/* ====================================================================== */
-
-static void
-qof_session_init (QofSession *session)
-{
- if (!session) return;
-
- session->entity.e_type = QOF_ID_SESSION;
- session->books = g_list_append (NULL, qof_book_new ());
- session->book_id = NULL;
- session->backend = NULL;
-
- qof_session_clear_error (session);
-}
-
-QofSession *
-qof_session_new (void)
-{
- QofSession *session = g_new0(QofSession, 1);
- qof_session_init(session);
- return session;
-}
-
-/** \deprecated Each application should keep
-their \b own session context. */
-QofSession *
-qof_session_get_current_session (void)
-{
- if (!current_session)
- {
- gnc_engine_suspend_events ();
- current_session = qof_session_new ();
- gnc_engine_resume_events ();
- }
-
- return current_session;
-}
-
-/** \deprecated Each application should keep
-their \b own session context. */
-void
-qof_session_set_current_session (QofSession *session)
-{
- current_session = session;
-}
-
-QofBook *
-qof_session_get_book (QofSession *session)
-{
- GList *node;
- if (!session) return NULL;
-
- for (node=session->books; node; node=node->next)
- {
- QofBook *book = node->data;
- if ('y' == book->book_open) return book;
- }
- return NULL;
-}
-
-void
-qof_session_add_book (QofSession *session, QofBook *addbook)
-{
- GList *node;
- if (!session) return;
-
- ENTER (" sess=%p book=%p", session, addbook);
-
- /* See if this book is already there ... */
- for (node=session->books; node; node=node->next)
- {
- QofBook *book = node->data;
- if (addbook == book) return;
- }
-
- if ('y' == addbook->book_open)
- {
- /* hack alert -- someone should free all the books in the list,
- * but it should probably not be us ... since the books backends
- * should be shutdown first, etc */
-/* XXX this should probably be an error XXX */
- g_list_free (session->books);
- session->books = g_list_append (NULL, addbook);
- }
- else
- {
-/* XXX Need to tell the backend to add a book as well */
- session->books = g_list_append (session->books, addbook);
- }
-
- qof_book_set_backend (addbook, session->backend);
- LEAVE (" ");
-}
-
-QofBackend *
-qof_session_get_backend (QofSession *session)
-{
- if (!session) return NULL;
- return session->backend;
-}
-
-const char *
-qof_session_get_file_path (QofSession *session)
-{
- if (!session) return NULL;
- if (!session->backend) return NULL;
- return session->backend->fullpath;
-}
-
-const char *
-qof_session_get_url (QofSession *session)
-{
- if (!session) return NULL;
- return session->book_id;
-}
-
-/* =============================================================== */
-
-typedef struct qof_entity_copy_data {
- QofEntity *from;
- QofEntity *to;
- GList *referenceList;
- GSList *param_list;
- QofSession *new_session;
- gboolean error;
-}QofEntityCopyData;
-
-static void
-qof_book_set_partial(QofBook *book)
-{
- gboolean partial;
-
- partial =
- (gboolean)GPOINTER_TO_INT(qof_book_get_data(book, PARTIAL_QOFBOOK));
- if(!partial) {
- qof_book_set_data(book, PARTIAL_QOFBOOK, (gboolean*)TRUE);
- }
-}
-
-void
-qof_session_update_reference_list(QofSession *session, QofEntityReference *reference)
-{
- QofBook *book;
- GList *book_ref_list;
-
- book = qof_session_get_book(session);
- book_ref_list = (GList*)qof_book_get_data(book, ENTITYREFERENCE);
- book_ref_list = g_list_append(book_ref_list, reference);
- qof_book_set_data(book, ENTITYREFERENCE, book_ref_list);
- qof_book_set_partial(book);
-}
-
-static void
-qof_entity_param_cb(QofParam *param, gpointer data)
-{
- QofEntityCopyData *qecd;
-
- g_return_if_fail(data != NULL);
- qecd = (QofEntityCopyData*)data;
- g_return_if_fail(param != NULL);
- if((param->param_getfcn != NULL)&&(param->param_setfcn != NULL)) {
- qecd->param_list = g_slist_prepend(qecd->param_list, param);
- }
-}
-
-QofEntityReference*
-qof_entity_get_reference_from(QofEntity *ent, const QofParam *param)
-{
- QofEntityReference *reference;
- QofEntity *ref_ent;
- const GUID *cm_guid;
- char cm_sa[GUID_ENCODING_LENGTH + 1];
- gchar *cm_string;
-
- g_return_val_if_fail(param, NULL);
- ref_ent = (QofEntity*)param->param_getfcn(ent, param);
- if(ref_ent != NULL) {
- reference = g_new0(QofEntityReference, 1);
- reference->type = ent->e_type;
- reference->ref_guid = g_new(GUID, 1);
- reference->ent_guid = &ent->guid;
- reference->param = qof_class_get_parameter(ent->e_type, param->param_name);
- cm_guid = qof_entity_get_guid(ref_ent);
- guid_to_string_buff(cm_guid, cm_sa);
- cm_string = g_strdup(cm_sa);
- if(TRUE == string_to_guid(cm_string, reference->ref_guid)) {
- return reference;
- }
- }
- return NULL;
-}
-
-static void
-qof_entity_foreach_copy(gpointer data, gpointer user_data)
-{
- QofEntity *importEnt, *targetEnt, *referenceEnt;
- QofEntityCopyData *context;
- QofEntityReference *reference;
- gboolean registered_type;
- /* cm_ prefix used for variables that hold the data to commit */
- QofParam *cm_param;
- gchar *cm_string, *cm_char;
- const GUID *cm_guid;
- KvpFrame *cm_kvp;
- /* function pointers and variables for parameter getters that don't use pointers normally */
- gnc_numeric cm_numeric, (*numeric_getter) (QofEntity*, QofParam*);
- double cm_double, (*double_getter) (QofEntity*, QofParam*);
- gboolean cm_boolean, (*boolean_getter) (QofEntity*, QofParam*);
- gint32 cm_i32, (*int32_getter) (QofEntity*, QofParam*);
- gint64 cm_i64, (*int64_getter) (QofEntity*, QofParam*);
- Timespec cm_date, (*date_getter) (QofEntity*, QofParam*);
- /* function pointers to the parameter setters */
- void (*string_setter) (QofEntity*, const char*);
- void (*date_setter) (QofEntity*, Timespec);
- void (*numeric_setter) (QofEntity*, gnc_numeric);
- void (*guid_setter) (QofEntity*, const GUID*);
- void (*double_setter) (QofEntity*, double);
- void (*boolean_setter) (QofEntity*, gboolean);
- void (*i32_setter) (QofEntity*, gint32);
- void (*i64_setter) (QofEntity*, gint64);
- void (*char_setter) (QofEntity*, char*);
- void (*kvp_frame_setter) (QofEntity*, KvpFrame*);
-
- g_return_if_fail(user_data != NULL);
- context = (QofEntityCopyData*) user_data;
- cm_date.tv_nsec = 0;
- cm_date.tv_sec = 0;
- importEnt = context->from;
- targetEnt = context->to;
- registered_type = FALSE;
- cm_param = (QofParam*) data;
- g_return_if_fail(cm_param != NULL);
- if(safe_strcmp(cm_param->param_type, QOF_TYPE_STRING) == 0) {
- cm_string = g_strdup((gchar*)cm_param->param_getfcn(importEnt, cm_param));
- string_setter = (void(*)(QofEntity*, const char*))cm_param->param_setfcn;
- if(string_setter != NULL) { string_setter(targetEnt, cm_string); }
- registered_type = TRUE;
- }
- if(safe_strcmp(cm_param->param_type, QOF_TYPE_DATE) == 0) {
- date_getter = (Timespec (*)(QofEntity*, QofParam*))cm_param->param_getfcn;
- cm_date = date_getter(importEnt, cm_param);
- date_setter = (void(*)(QofEntity*, Timespec))cm_param->param_setfcn;
- if(date_setter != NULL) { date_setter(targetEnt, cm_date); }
- registered_type = TRUE;
- }
- if((safe_strcmp(cm_param->param_type, QOF_TYPE_NUMERIC) == 0) ||
- (safe_strcmp(cm_param->param_type, QOF_TYPE_DEBCRED) == 0)) {
- numeric_getter = (gnc_numeric (*)(QofEntity*, QofParam*))cm_param->param_getfcn;
- cm_numeric = numeric_getter(importEnt, cm_param);
- numeric_setter = (void(*)(QofEntity*, gnc_numeric))cm_param->param_setfcn;
- if(numeric_setter != NULL) { numeric_setter(targetEnt, cm_numeric); }
- registered_type = TRUE;
- }
- if(safe_strcmp(cm_param->param_type, QOF_TYPE_GUID) == 0) {
- cm_guid = (const GUID*)cm_param->param_getfcn(importEnt, cm_param);
- guid_setter = (void(*)(QofEntity*, const GUID*))cm_param->param_setfcn;
- if(guid_setter != NULL) { guid_setter(targetEnt, cm_guid); }
- registered_type = TRUE;
- }
- if(safe_strcmp(cm_param->param_type, QOF_TYPE_INT32) == 0) {
- int32_getter = (gint32 (*)(QofEntity*, QofParam*)) cm_param->param_getfcn;
- cm_i32 = int32_getter(importEnt, cm_param);
- i32_setter = (void(*)(QofEntity*, gint32))cm_param->param_setfcn;
- if(i32_setter != NULL) { i32_setter(targetEnt, cm_i32); }
- registered_type = TRUE;
- }
- if(safe_strcmp(cm_param->param_type, QOF_TYPE_INT64) == 0) {
- int64_getter = (gint64 (*)(QofEntity*, QofParam*)) cm_param->param_getfcn;
- cm_i64 = int64_getter(importEnt, cm_param);
- i64_setter = (void(*)(QofEntity*, gint64))cm_param->param_setfcn;
- if(i64_setter != NULL) { i64_setter(targetEnt, cm_i64); }
- registered_type = TRUE;
- }
- if(safe_strcmp(cm_param->param_type, QOF_TYPE_DOUBLE) == 0) {
- double_getter = (double (*)(QofEntity*, QofParam*)) cm_param->param_getfcn;
- cm_double = double_getter(importEnt, cm_param);
- double_setter = (void(*)(QofEntity*, double))cm_param->param_setfcn;
- if(double_setter != NULL) { double_setter(targetEnt, cm_double); }
- registered_type = TRUE;
- }
- if(safe_strcmp(cm_param->param_type, QOF_TYPE_BOOLEAN) == 0){
- boolean_getter = (gboolean (*)(QofEntity*, QofParam*)) cm_param->param_getfcn;
- cm_boolean = boolean_getter(importEnt, cm_param);
- boolean_setter = (void(*)(QofEntity*, gboolean))cm_param->param_setfcn;
- if(boolean_setter != NULL) { boolean_setter(targetEnt, cm_boolean); }
- registered_type = TRUE;
- }
- if(safe_strcmp(cm_param->param_type, QOF_TYPE_KVP) == 0) {
- cm_kvp = kvp_frame_copy((KvpFrame*)cm_param->param_getfcn(importEnt,cm_param));
- kvp_frame_setter = (void(*)(QofEntity*, KvpFrame*))cm_param->param_setfcn;
- if(kvp_frame_setter != NULL) { kvp_frame_setter(targetEnt, cm_kvp); }
- registered_type = TRUE;
- }
- if(safe_strcmp(cm_param->param_type, QOF_TYPE_CHAR) == 0) {
- cm_char = (gchar*)cm_param->param_getfcn(importEnt,cm_param);
- char_setter = (void(*)(QofEntity*, char*))cm_param->param_setfcn;
- if(char_setter != NULL) { char_setter(targetEnt, cm_char); }
- registered_type = TRUE;
- }
- if(registered_type == FALSE) {
- referenceEnt = (QofEntity*)cm_param->param_getfcn(importEnt, cm_param);
- if(!referenceEnt || !referenceEnt->e_type) { return; }
- reference = qof_entity_get_reference_from(importEnt, cm_param);
- if(reference) {
- qof_session_update_reference_list(context->new_session, reference);
- }
- }
-}
-
-static gboolean
-qof_entity_guid_match(QofSession *new_session, QofEntity *original)
-{
- QofEntity *copy;
- const GUID *g;
- QofIdTypeConst type;
- QofBook *targetBook;
- QofCollection *coll;
-
- copy = NULL;
- g_return_val_if_fail(original != NULL, FALSE);
- targetBook = qof_session_get_book(new_session);
- g_return_val_if_fail(targetBook != NULL, FALSE);
- g = qof_entity_get_guid(original);
- type = g_strdup(original->e_type);
- coll = qof_book_get_collection(targetBook, type);
- copy = qof_collection_lookup_entity(coll, g);
- if(copy) { return TRUE; }
- return FALSE;
-}
-
-static void
-qof_entity_list_foreach(gpointer data, gpointer user_data)
-{
- QofEntityCopyData *qecd;
- QofEntity *original;
- QofInstance *inst;
- QofBook *book;
- const GUID *g;
-
- g_return_if_fail(data != NULL);
- original = (QofEntity*)data;
- g_return_if_fail(user_data != NULL);
- qecd = (QofEntityCopyData*)user_data;
- if(qof_entity_guid_match(qecd->new_session, original)) { return; }
- qecd->from = original;
- book = qof_session_get_book(qecd->new_session);
- inst = (QofInstance*)qof_object_new_instance(original->e_type, book);
- qecd->to = &inst->entity;
- g = qof_entity_get_guid(original);
- qof_entity_set_guid(qecd->to, g);
- if(qecd->param_list != NULL) {
- g_slist_free(qecd->param_list);
- qecd->param_list = NULL;
- }
- qof_class_param_foreach(original->e_type, qof_entity_param_cb, qecd);
- qof_begin_edit(inst);
- g_slist_foreach(qecd->param_list, qof_entity_foreach_copy, qecd);
- qof_commit_edit(inst);
-}
-
-static void
-qof_entity_coll_foreach(QofEntity *original, gpointer user_data)
-{
- QofEntityCopyData *qecd;
- const GUID *g;
- QofBook *targetBook;
- QofCollection *coll;
- QofEntity *copy;
-
- g_return_if_fail(user_data != NULL);
- copy = NULL;
- qecd = (QofEntityCopyData*)user_data;
- targetBook = qof_session_get_book(qecd->new_session);
- g = qof_entity_get_guid(original);
- coll = qof_book_get_collection(targetBook, original->e_type);
- copy = qof_collection_lookup_entity(coll, g);
- if(copy) { qecd->error = TRUE; }
-}
-
-static void
-qof_entity_coll_copy(QofEntity *original, gpointer user_data)
-{
- QofEntityCopyData *qecd;
- QofBook *book;
- QofInstance *inst;
- const GUID *g;
-
- g_return_if_fail(user_data != NULL);
- qecd = (QofEntityCopyData*)user_data;
- book = qof_session_get_book(qecd->new_session);
- inst = (QofInstance*)qof_object_new_instance(original->e_type, book);
- qecd->to = &inst->entity;
- qecd->from = original;
- g = qof_entity_get_guid(original);
- qof_entity_set_guid(qecd->to, g);
- qof_begin_edit(inst);
- g_slist_foreach(qecd->param_list, qof_entity_foreach_copy, qecd);
- qof_commit_edit(inst);
-}
-
-gboolean qof_entity_copy_to_session(QofSession* new_session, QofEntity* original)
-{
- QofEntityCopyData qecd;
- QofInstance *inst;
- QofBook *book;
-
- if(!new_session || !original) { return FALSE; }
- if(qof_entity_guid_match(new_session, original)) { return FALSE; }
- gnc_engine_suspend_events();
- qecd.param_list = NULL;
- book = qof_session_get_book(new_session);
- qecd.new_session = new_session;
- qof_book_set_partial(book);
- inst = (QofInstance*)qof_object_new_instance(original->e_type, book);
- qecd.to = &inst->entity;
- qecd.from = original;
- qof_entity_set_guid(qecd.to, qof_entity_get_guid(original));
- qof_begin_edit(inst);
- qof_class_param_foreach(original->e_type, qof_entity_param_cb, &qecd);
- qof_commit_edit(inst);
- if(g_slist_length(qecd.param_list) == 0) { return FALSE; }
- g_slist_foreach(qecd.param_list, qof_entity_foreach_copy, &qecd);
- g_slist_free(qecd.param_list);
- gnc_engine_resume_events();
- return TRUE;
-}
-
-gboolean qof_entity_copy_list(QofSession *new_session, GList *entity_list)
-{
- QofEntityCopyData *qecd;
-
- if(!new_session || !entity_list) { return FALSE; }
- ENTER (" list=%d", g_list_length(entity_list));
- qecd = g_new0(QofEntityCopyData, 1);
- gnc_engine_suspend_events();
- qecd->param_list = NULL;
- qecd->new_session = new_session;
- qof_book_set_partial(qof_session_get_book(new_session));
- g_list_foreach(entity_list, qof_entity_list_foreach, qecd);
- gnc_engine_resume_events();
- g_free(qecd);
- LEAVE (" ");
- return TRUE;
-}
-
-gboolean qof_entity_copy_coll(QofSession *new_session, QofCollection *entity_coll)
-{
- QofEntityCopyData qecd;
-
- gnc_engine_suspend_events();
- qecd.param_list = NULL;
- qecd.new_session = new_session;
- qof_book_set_partial(qof_session_get_book(qecd.new_session));
- qof_collection_foreach(entity_coll, qof_entity_coll_foreach, &qecd);
- qof_class_param_foreach(qof_collection_get_type(entity_coll), qof_entity_param_cb, &qecd);
- qof_collection_foreach(entity_coll, qof_entity_coll_copy, &qecd);
- if(qecd.param_list != NULL) { g_slist_free(qecd.param_list); }
- gnc_engine_resume_events();
- return TRUE;
-}
-
-struct recurse_s
-{
- QofSession *session;
- gboolean success;
- GList *ref_list;
- GList *ent_list;
-};
-
-static void
-recurse_collection_cb (QofEntity *ent, gpointer user_data)
-{
- struct recurse_s *store;
-
- if(user_data == NULL) { return; }
- store = (struct recurse_s*)user_data;
- if(!ent || !store) { return; }
- store->success = qof_entity_copy_to_session(store->session, ent);
- if(store->success) {
- store->ent_list = g_list_append(store->ent_list, ent);
- }
-}
-
-static void
-recurse_ent_cb(QofEntity *ent, gpointer user_data)
-{
- GList *ref_list, *i, *j, *ent_list, *child_list;
- QofParam *ref_param;
- QofEntity *ref_ent, *child_ent;
- QofSession *session;
- struct recurse_s *store;
- gboolean success;
-
- if(user_data == NULL) { return; }
- store = (struct recurse_s*)user_data;
- session = store->session;
- success = store->success;
- ref_list = NULL;
- child_ent = NULL;
- ref_list = g_list_copy(store->ref_list);
- if((!session)||(!ent)) { return; }
- ent_list = NULL;
- child_list = NULL;
- i = NULL;
- j = NULL;
- for(i = ref_list; i != NULL; i=i->next)
- {
- if(i->data == NULL) { continue; }
- ref_param = (QofParam*)i->data;
- if(ref_param->param_name == NULL) { continue; }
- if(ref_param->param_type == QOF_TYPE_COLLECT) {
- QofCollection *col;
- col = ref_param->param_getfcn(ent, ref_param);
- qof_collection_foreach(col, recurse_collection_cb, store);
- continue;
- }
- ref_ent = (QofEntity*)ref_param->param_getfcn(ent, ref_param);
- if((ref_ent)&&(ref_ent->e_type))
- {
- store->success = qof_entity_copy_to_session(session, ref_ent);
- if(store->success) { ent_list = g_list_append(ent_list, ref_ent); }
- }
- }
- for(i = ent_list; i != NULL; i = i->next)
- {
- if(i->data == NULL) { continue; }
- child_ent = (QofEntity*)i->data;
- if(child_ent == NULL) { continue; }
- ref_list = qof_class_get_referenceList(child_ent->e_type);
- for(j = ref_list; j != NULL; j = j->next)
- {
- if(j->data == NULL) { continue; }
- ref_param = (QofParam*)j->data;
- ref_ent = ref_param->param_getfcn(child_ent, ref_param);
- if(ref_ent != NULL)
- {
- success = qof_entity_copy_to_session(session, ref_ent);
- if(success) { child_list = g_list_append(child_list, ref_ent); }
- }
- }
- }
- for(i = child_list; i != NULL; i = i->next)
- {
- if(i->data == NULL) { continue; }
- ref_ent = (QofEntity*)i->data;
- if(ref_ent == NULL) { continue; }
- ref_list = qof_class_get_referenceList(ref_ent->e_type);
- for(j = ref_list; j != NULL; j = j->next)
- {
- if(j->data == NULL) { continue; }
- ref_param = (QofParam*)j->data;
- child_ent = ref_param->param_getfcn(ref_ent, ref_param);
- if(child_ent != NULL)
- {
- qof_entity_copy_to_session(session, child_ent);
- }
- }
- }
-}
-
-gboolean
-qof_entity_copy_coll_r(QofSession *new_session, QofCollection *coll)
-{
- struct recurse_s store;
- gboolean success;
-
- if((!new_session)||(!coll)) { return FALSE; }
- store.session = new_session;
- success = TRUE;
- store.success = success;
- store.ent_list = NULL;
- store.ref_list = qof_class_get_referenceList(qof_collection_get_type(coll));
- success = qof_entity_copy_coll(new_session, coll);
- if(success){ qof_collection_foreach(coll, recurse_ent_cb, &store); }
- return success;
-}
-
-gboolean qof_entity_copy_one_r(QofSession *new_session, QofEntity *ent)
-{
- struct recurse_s store;
- QofCollection *coll;
- gboolean success;
-
- if((!new_session)||(!ent)) { return FALSE; }
- store.session = new_session;
- success = TRUE;
- store.success = success;
- store.ref_list = qof_class_get_referenceList(ent->e_type);
- success = qof_entity_copy_to_session(new_session, ent);
- if(success == TRUE) {
- coll = qof_book_get_collection(qof_session_get_book(new_session), ent->e_type);
- qof_collection_foreach(coll, recurse_ent_cb, &store);
- }
- return success;
-}
-
-
-/* ====================================================================== */
-
-/* Programs that use their own backends also need to call
-the default QOF ones. The backends specified here are
-loaded only by applications that do not have their own. */
-struct backend_providers
-{
- const char *libdir;
- const char *filename;
- const char *init_fcn;
-};
-
-/* All available QOF backends need to be described here
-and the last entry must be three NULL's.
-Remember: Use the libdir from the current build environment
-and use the .la NOT the .so - .so is not portable! */
-struct backend_providers backend_list[] = {
- { QOF_LIB_DIR, "libqof-backend-qsf.la", "qsf_provider_init" },
-#ifdef HAVE_DWI
- { QOF_LIB_DIR, "libqof_backend_dwi.la", "dwiend_provider_init" },
-#endif
- { NULL, NULL, NULL }
-};
-
-static void
-qof_session_load_backend(QofSession * session, char * access_method)
-{
- GSList *p;
- GList *node;
- QofBackendProvider *prov;
- QofBook *book;
- char *msg;
- gint num;
- gboolean prov_type;
- gboolean (*type_check) (const char*);
-
- ENTER (" list=%d", g_slist_length(provider_list));
- prov_type = FALSE;
- if (NULL == provider_list)
- {
- for (num = 0; backend_list[num].filename != NULL; num++) {
- if(!qof_load_backend_library(backend_list[num].libdir,
- backend_list[num].filename, backend_list[num].init_fcn))
- {
- PWARN (" failed to load %s from %s using %s",
- backend_list[num].filename, backend_list[num].libdir,
- backend_list[num].init_fcn);
- }
- }
- }
- p = g_slist_copy(provider_list);
- while(p != NULL)
- {
- prov = p->data;
- /* Does this provider handle the desired access method? */
- if (0 == strcasecmp (access_method, prov->access_method))
- {
- /* More than one backend could provide this
- access method, check file type compatibility. */
- type_check = (gboolean (*)(const char*)) prov->check_data_type;
- prov_type = (type_check)(session->book_id);
- if(!prov_type)
- {
- PINFO(" %s not usable", prov->provider_name);
- p = p->next;
- continue;
- }
- PINFO (" selected %s", prov->provider_name);
- if (NULL == prov->backend_new)
- {
- p = p->next;
- continue;
- }
- /* Use the providers creation callback */
- session->backend = (*(prov->backend_new))();
- session->backend->provider = prov;
- /* Tell the books about the backend that they'll be using. */
- for (node=session->books; node; node=node->next)
- {
- book = node->data;
- qof_book_set_backend (book, session->backend);
- }
- LEAVE (" ");
- return;
- }
- p = p->next;
- }
- msg = g_strdup_printf("failed to load '%s' using access_method", access_method);
- qof_session_push_error (session, ERR_BACKEND_NO_HANDLER, msg);
- LEAVE (" ");
-}
-
-/* ====================================================================== */
-
-static void
-qof_session_destroy_backend (QofSession *session)
-{
- g_return_if_fail (session);
-
- if (session->backend)
- {
- /* clear any error message */
- char * msg = qof_backend_get_message (session->backend);
- g_free (msg);
-
- /* Then destroy the backend */
- if (session->backend->destroy_backend)
- {
- session->backend->destroy_backend(session->backend);
- }
- else
- {
- g_free(session->backend);
- }
- }
-
- session->backend = NULL;
-}
-
-void
-qof_session_begin (QofSession *session, const char * book_id,
- gboolean ignore_lock, gboolean create_if_nonexistent)
-{
- char *p, *access_method, *msg;
- int err;
-
- if (!session) return;
-
- ENTER (" sess=%p ignore_lock=%d, book-id=%s",
- session, ignore_lock,
- book_id ? book_id : "(null)");
-
- /* Clear the error condition of previous errors */
- qof_session_clear_error (session);
-
- /* Check to see if this session is already open */
- if (session->book_id)
- {
- qof_session_push_error (session, ERR_BACKEND_LOCKED, NULL);
- LEAVE("push error book is already open ");
- return;
- }
-
- /* seriously invalid */
- if (!book_id)
- {
- qof_session_push_error (session, ERR_BACKEND_BAD_URL, NULL);
- LEAVE("push error missing book_id");
- return;
- }
-
- /* Store the session URL */
- session->book_id = g_strdup (book_id);
-
- /* destroy the old backend */
- qof_session_destroy_backend(session);
-
- /* Look for something of the form of "file:/", "http://" or
- * "postgres://". Everything before the colon is the access
- * method. Load the first backend found for that access method.
- */
- p = strchr (book_id, ':');
- if (p)
- {
- access_method = g_strdup (book_id);
- p = strchr (access_method, ':');
- *p = 0;
- qof_session_load_backend(session, access_method);
- g_free (access_method);
- }
- else
- {
- /* If no colon found, assume it must be a file-path */
- qof_session_load_backend(session, "file");
- }
-
- /* No backend was found. That's bad. */
- if (NULL == session->backend)
- {
- qof_session_push_error (session, ERR_BACKEND_BAD_URL, NULL);
- LEAVE (" BAD: no backend: sess=%p book-id=%s",
- session, book_id ? book_id : "(null)");
- return;
- }
-
- /* If there's a begin method, call that. */
- if (session->backend->session_begin)
- {
-
- (session->backend->session_begin)(session->backend, session,
- session->book_id, ignore_lock,
- create_if_nonexistent);
- PINFO("Done running session_begin on backend");
- err = qof_backend_get_error(session->backend);
- msg = qof_backend_get_message(session->backend);
- if (err != ERR_BACKEND_NO_ERR)
- {
- g_free(session->book_id);
- session->book_id = NULL;
- qof_session_push_error (session, err, msg);
- LEAVE(" backend error %d %s", err, msg);
- return;
- }
- if (msg != NULL)
- {
- PWARN("%s", msg);
- g_free(msg);
- }
- }
-
- LEAVE (" sess=%p book-id=%s",
- session, book_id ? book_id : "(null)");
-}
-
-/* ====================================================================== */
-
-void
-qof_session_load (QofSession *session,
- QofPercentageFunc percentage_func)
-{
- QofBook *newbook, *ob;
- QofBookList *oldbooks, *node;
- QofBackend *be;
- QofBackendError err;
-
- if (!session) return;
- if (!session->book_id) return;
-
- ENTER ("sess=%p book_id=%s", session, session->book_id
- ? session->book_id : "(null)");
-
- /* At this point, we should are supposed to have a valid book
- * id and a lock on the file. */
-
- oldbooks = session->books;
-
- /* XXX why are we creating a book here? I think the books
- * need to be handled by the backend ... especially since
- * the backend may need to load multiple books ... XXX. FIXME.
- */
- newbook = qof_book_new();
- session->books = g_list_append (NULL, newbook);
- PINFO ("new book=%p", newbook);
-
- qof_session_clear_error (session);
-
- /* This code should be sufficient to initialize *any* backend,
- * whether http, postgres, or anything else that might come along.
- * Basically, the idea is that by now, a backend has already been
- * created & set up. At this point, we only need to get the
- * top-level account group out of the backend, and that is a
- * generic, backend-independent operation.
- */
- be = session->backend;
- qof_book_set_backend(newbook, be);
-
- /* Starting the session should result in a bunch of accounts
- * and currencies being downloaded, but probably no transactions;
- * The GUI will need to do a query for that.
- */
- if (be)
- {
- be->percentage = percentage_func;
-
- if (be->load)
- {
- be->load (be, newbook);
- qof_session_push_error (session, qof_backend_get_error(be), NULL);
- }
- }
-
- /* XXX if the load fails, then we try to restore the old set of books;
- * however, we don't undo the session id (the URL). Thus if the
- * user attempts to save after a failed load, they weill be trying to
- * save to some bogus URL. This is wrong. XXX FIXME.
- */
- err = qof_session_get_error(session);
- if ((err != ERR_BACKEND_NO_ERR) &&
- (err != ERR_FILEIO_FILE_TOO_OLD) &&
- (err != ERR_SQL_DB_TOO_OLD))
- {
- /* Something broke, put back the old stuff */
- qof_book_set_backend (newbook, NULL);
- qof_book_destroy (newbook);
- g_list_free (session->books);
- session->books = oldbooks;
- LEAVE("error from backend %d", qof_session_get_error(session));
- return;
- }
-
- for (node=oldbooks; node; node=node->next)
- {
- ob = node->data;
- qof_book_set_backend (ob, NULL);
- qof_book_destroy (ob);
- }
- /* Um, I think we're leaking the oldbooks list. */
-
- LEAVE ("sess = %p, book_id=%s", session, session->book_id
- ? session->book_id : "(null)");
-}
-
-/* ====================================================================== */
-
-gboolean
-qof_session_save_may_clobber_data (QofSession *session)
-{
- if (!session) return FALSE;
- if (!session->backend) return FALSE;
- if (!session->backend->save_may_clobber_data) return FALSE;
-
- return (*(session->backend->save_may_clobber_data)) (session->backend);
-}
-
-static gboolean
-save_error_handler(QofBackend *be, QofSession *session)
-{
- int err;
- err = qof_backend_get_error(be);
-
- if (ERR_BACKEND_NO_ERR != err)
- {
- qof_session_push_error (session, err, NULL);
- return TRUE;
- }
- return FALSE;
-}
-
-void
-qof_session_save (QofSession *session,
- QofPercentageFunc percentage_func)
-{
- GList *node;
- QofBackend *be;
- gboolean partial, change_backend;
- QofBackendProvider *prov;
- GSList *p;
- QofBook *book, *abook;
- int err;
- gint num;
- char *msg, *book_id;
-
- if (!session) return;
- ENTER ("sess=%p book_id=%s",
- session, session->book_id ? session->book_id : "(null)");
- /* Partial book handling. */
- book = qof_session_get_book(session);
- partial = (gboolean)GPOINTER_TO_INT(qof_book_get_data(book, PARTIAL_QOFBOOK));
- change_backend = FALSE;
- msg = g_strdup_printf(" ");
- book_id = g_strdup(session->book_id);
- if(partial == TRUE)
- {
- if(session->backend && session->backend->provider) {
- prov = session->backend->provider;
- if(TRUE == prov->partial_book_supported)
- {
- /* if current backend supports partial, leave alone. */
- change_backend = FALSE;
- }
- else { change_backend = TRUE; }
- }
- /* If provider is undefined, assume partial not supported. */
- else { change_backend = TRUE; }
- }
- if(change_backend == TRUE)
- {
- qof_session_destroy_backend(session);
- if (NULL == provider_list)
- {
- for (num = 0; backend_list[num].filename != NULL; num++) {
- qof_load_backend_library(backend_list[num].libdir,
- backend_list[num].filename, backend_list[num].init_fcn);
- }
- }
- p = g_slist_copy(provider_list);
- while(p != NULL)
- {
- prov = p->data;
- if(TRUE == prov->partial_book_supported)
- {
- /** \todo check the access_method too, not in scope here, yet. */
- /* if((TRUE == prov->partial_book_supported) &&
- (0 == strcasecmp (access_method, prov->access_method)))
- {*/
- if (NULL == prov->backend_new) continue;
- /* Use the providers creation callback */
- session->backend = (*(prov->backend_new))();
- session->backend->provider = prov;
- if (session->backend->session_begin)
- {
- /* Call begin - backend has been changed,
- so make sure a file can be written,
- use ignore_lock and create_if_nonexistent */
- g_free(session->book_id);
- session->book_id = NULL;
- (session->backend->session_begin)(session->backend, session,
- book_id, TRUE, TRUE);
- PINFO("Done running session_begin on changed backend");
- err = qof_backend_get_error(session->backend);
- msg = qof_backend_get_message(session->backend);
- if (err != ERR_BACKEND_NO_ERR)
- {
- g_free(session->book_id);
- session->book_id = NULL;
- qof_session_push_error (session, err, msg);
- LEAVE("changed backend error %d", err);
- return;
- }
- if (msg != NULL)
- {
- PWARN("%s", msg);
- g_free(msg);
- }
- }
- /* Tell the books about the backend that they'll be using. */
- for (node=session->books; node; node=node->next)
- {
- book = node->data;
- qof_book_set_backend (book, session->backend);
- }
- p = NULL;
- }
- if(p) {
- p = p->next;
- }
- }
- if(!session->backend)
- {
- msg = g_strdup_printf("failed to load backend");
- qof_session_push_error(session, ERR_BACKEND_NO_HANDLER, msg);
- return;
- }
- }
- /* If there is a backend, and the backend is reachable
- * (i.e. we can communicate with it), then synchronize with
- * the backend. If we cannot contact the backend (e.g.
- * because we've gone offline, the network has crashed, etc.)
- * then give the user the option to save to the local disk.
- *
- * hack alert -- FIXME -- XXX the code below no longer
- * does what the words above say. This needs fixing.
- */
- be = session->backend;
- if (be)
- {
- for (node = session->books; node; node=node->next)
- {
- abook = node->data;
- /* if invoked as SaveAs(), then backend not yet set */
- qof_book_set_backend (abook, be);
- be->percentage = percentage_func;
- if (be->sync)
- {
- (be->sync)(be, abook);
- if (save_error_handler(be, session)) return;
- }
- }
- /* If we got to here, then the backend saved everything
- * just fine, and we are done. So return. */
- /* Return the book_id to previous value. */
- qof_session_clear_error (session);
- LEAVE("Success");
- return;
- }
- else
- {
- msg = g_strdup_printf("failed to load backend");
- qof_session_push_error(session, ERR_BACKEND_NO_HANDLER, msg);
- }
- LEAVE("error -- No backend!");
-}
-
-/* ====================================================================== */
-
-void
-qof_session_end (QofSession *session)
-{
- if (!session) return;
-
- ENTER ("sess=%p book_id=%s", session, session->book_id
- ? session->book_id : "(null)");
-
- /* close down the backend first */
- if (session->backend && session->backend->session_end)
- {
- (session->backend->session_end)(session->backend);
- }
-
- qof_session_clear_error (session);
-
- g_free (session->book_id);
- session->book_id = NULL;
-
- LEAVE ("sess=%p book_id=%s", session, session->book_id
- ? session->book_id : "(null)");
-}
-
-void
-qof_session_destroy (QofSession *session)
-{
- GList *node;
- if (!session) return;
-
- ENTER ("sess=%p book_id=%s", session, session->book_id
- ? session->book_id : "(null)");
-
- qof_session_end (session);
-
- /* destroy the backend */
- qof_session_destroy_backend(session);
-
- for (node = session->books; node; node = node->next)
- {
- QofBook *book = node->data;
- qof_book_set_backend (book, NULL);
- qof_book_destroy (book);
- }
-
- session->books = NULL;
- if (session == current_session)
- current_session = NULL;
-
- g_free (session);
-
- LEAVE ("sess=%p", session);
-}
-
-/* ====================================================================== */
-/* this call is weird. */
-
-void
-qof_session_swap_data (QofSession *session_1, QofSession *session_2)
-{
- GList *books_1, *books_2, *node;
-
- if (session_1 == session_2) return;
- if (!session_1 || !session_2) return;
-
- ENTER ("sess1=%p sess2=%p", session_1, session_2);
-
- books_1 = session_1->books;
- books_2 = session_2->books;
-
- session_1->books = books_2;
- session_2->books = books_1;
-
- for (node=books_1; node; node=node->next)
- {
- QofBook *book_1 = node->data;
- qof_book_set_backend (book_1, session_2->backend);
- }
- for (node=books_2; node; node=node->next)
- {
- QofBook *book_2 = node->data;
- qof_book_set_backend (book_2, session_1->backend);
- }
-
- LEAVE (" ");
-}
-
-/* ====================================================================== */
-
-gboolean
-qof_session_events_pending (QofSession *session)
-{
- if (!session) return FALSE;
- if (!session->backend) return FALSE;
- if (!session->backend->events_pending) return FALSE;
-
- return session->backend->events_pending (session->backend);
-}
-
-gboolean
-qof_session_process_events (QofSession *session)
-{
- if (!session) return FALSE;
- if (!session->backend) return FALSE;
- if (!session->backend->process_events) return FALSE;
-
- return session->backend->process_events (session->backend);
-}
-
-/* =================== END OF FILE ====================================== */
Deleted: gnucash/trunk/src/engine/qofsession.h
===================================================================
--- gnucash/trunk/src/engine/qofsession.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofsession.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,558 +0,0 @@
-/********************************************************************\
- * qofsession.h -- session access (connection to backend) *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-/** @addtogroup Backend
- *
- * The QOF Session
- * encapsulates a connection to a storage backend. That is, it
- * manages the connection to a persistant data store; whereas
- * the backend is the thing that performs the actual datastore
- * access.
- *
- * This class provides several important services:
- *
- * 1) It resolves and loads the appropriate backend, based on
- * the URL.
- *
- * 2) It reports backend errors (e.g. network errors, storage
- * corruption errors) through a single, backend-independent
- * API.
- *
- * 3) It reports non-error events received from the backend.
- *
- * 4) It helps manage global dataset locks. For example, for the
- * file backend, the lock prevents multiple users from editing
- * the same file at the same time, thus avoiding lost data due
- * to race conditions. Thus, an open session implies that the
- * associated file is locked.
- *
- * 5) Misc utilities, such as a search path for the file to be
- * edited, and/or other URL resolution utilities. This should
- * simplify install & maintenance problems for naive users who
- * may not have a good grasp on what a file system is, or where
- * they want to keep their data files.
- *
- * 6) In the future, this class is probably a good place to manage
- * a portion of the user authentication process, and hold user
- * credentials/cookies/keys/tokens. This is because at the
- * coarsest level, authorization can happen at the datastore
- * level: i.e. does this user even have the authority to connect
- * to and open this datastore?
- *
- * A brief note about books & sessions:
- * A book encapsulates the datasets manipulated by GnuCash. A book
- * holds the actual data. By contrast, the session mediates the
- * connection between a book (the thing that lives in virtual memory
- * in the local process) and the datastore (the place where book
- * data lives permanently, e.g., file, database).
- *
- * In the current design, a session may hold multiple books. For
- * now, exactly what this means is somewhat vague, and code in
- * various places makes some implicit assumptions: first, only
- * one book is 'current' and open for editing. Next, its assumed
- * that all of the books in a session are related in some way.
- * i.e. that they are all earlier accounting periods of the
- * currently open book. In particular, the backends probably
- * make that assumption, in order to store the different accounting
- * periods in a clump so that one can be found, given another.
- *
-
- The session now calls QofBackendProvider->check_data_type
- to check that the incoming path contains data that the
- backend provider can open. The backend provider should
- also check if it can contact it's storage media (disk,
- network, server, etc.) and abort if it can't. Malformed
- file URL's would be handled the same way.
-
- @{
- */
-
-/** @file qofsession.h
- * @brief Encapsulates a connection to a backend (persistent store)
- * @author Copyright (c) 1998, 1999, 2001, 2002 Linas Vepstas <linas at linas.org>
- * @author Copyright (c) 2000 Dave Peticolas
- * @author Copyright (c) 2005 Neil Williams <linux at codehelp.co.uk>
- */
-
-#ifndef QOF_SESSION_H
-#define QOF_SESSION_H
-
-#include "qofbackend.h"
-#include "qofbook.h"
-#include "qofclass.h"
-#include "qofobject.h"
-
-#define QOF_MOD_SESSION "qof-session"
-
-/* PROTOTYPES ******************************************************/
-
-typedef struct _QofSession QofSession;
-
-QofSession * qof_session_new (void);
-void qof_session_destroy (QofSession *session);
-QofSession * qof_session_get_current_session (void);
-void qof_session_set_current_session (QofSession *session);
-
-/** The qof_session_swap_data () method swaps the book of
- * the two given sessions. It is useful
- * for 'Save As' type functionality. */
-void qof_session_swap_data (QofSession *session_1, QofSession *session_2);
-
-/** The qof_session_begin () method begins a new session.
- * It takes as an argument the book id. The book id must be a string
- * in the form of a URI/URL.
- * In the current implementation, the following URL's are supported
- * -- File URI of the form
- * "file:/home/somewhere/somedir/file.xac"
- * The path part must be a valid path. The file-part must be
- * a valid old-style-xacc or new-style-gnucash-format file. Paths
- * may be relative or absolute. If the path is relative; that is,
- * if the argument is "file:somefile.xac" then a sequence of
- * search paths are checked for a file of this name.
- *
- * -- Postgres URI of the form
- * "postgres://hostname.com/dbname"
- * See the src/backend/postgres subdirectory for more info.
- *
- * -- RPC URI of the form rpc://hostname.com/rpcserver.
- *
- * The 'ignore_lock' argument, if set to TRUE, will cause this routine
- * to ignore any global-datastore locks (e.g. file locks) that it finds.
- * If set to FALSE, then file/database-global locks will be tested and
- * obeyed.
- *
- * If the datastore exists, can be reached (e.g over the net),
- * connected to, opened and read, and a lock can be obtained then
- * a lock will be obtained. Note that multi-user datastores
- * (e.g. the SQL backend) typically will not need to get a global
- * lock, and thus, the user will not be locked out. That's the
- * whole point of 'multi-user'.
- *
- * If the file/database doesn't exist, and the create_if_nonexistent
- * flag is set to TRUE, then the database is created.
- *
- * If an error occurs, it will be pushed onto the session error
- * stack, and that is where it should be examined.
- */
-void qof_session_begin (QofSession *session, const char * book_id,
- gboolean ignore_lock, gboolean create_if_nonexistent);
-
-
-/**
- * The qof_session_load() method causes the QofBook to be made ready to
- * to use with this URL/datastore. When the URL points at a file,
- * then this routine would load the data from the file. With remote
- * backends, e.g. network or SQL, this would load only enough data
- * to make the book actually usable; it would not cause *all* of the
- * data to be loaded.
- *
- * XXX the current design tries to accomodate multiple calls to 'load'
- * for each session, each time wiping out the old books; this seems
- * wrong to me, and should be restricted to allow only one load per
- * session.
- */
-typedef void (*QofPercentageFunc) (const char *message, double percent);
-void qof_session_load (QofSession *session,
- QofPercentageFunc percentage_func);
-
-/** @name Session Errors
- @{ */
-/** The qof_session_get_error() routine can be used to obtain the reason
- * for any failure. Calling this routine returns the current error.
- */
-QofBackendError qof_session_get_error (QofSession *session);
-const char * qof_session_get_error_message(QofSession *session);
-
-/**
- * The qof_session_pop_error() routine can be used to obtain the reason
- * for any failure. Calling this routine resets the error value.
- *
- * This routine allows an implementation of multiple error values,
- * e.g. in a stack, where this routine pops the top value. The current
- * implementation has a stack that is one-deep.
- *
- * See qofbackend.h for a listing of returned errors.
- */
-QofBackendError qof_session_pop_error (QofSession *session);
-/** @} */
-
-/** The qof_session_add_book() allows additional books to be added to
- * a session.
- * XXX Under construction, clarify the following when done:
- * XXX There must already be an open book in the session already!?
- * XXX Only one open book at a time per session is allowed!?
- * XXX each book gets its own unique backend ???
- */
-void qof_session_add_book (QofSession *session, QofBook *book);
-
-QofBook * qof_session_get_book (QofSession *session);
-
-/**
- * The qof_session_get_file_path() routine returns the fully-qualified file
- * path for the session. That is, if a relative or partial filename
- * was for the session, then it had to have been fully resolved to
- * open the session. This routine returns the result of this resolution.
- * The path is always guaranteed to reside in the local file system,
- * even if the session itself was opened as a URL. (currently, the
- * filepath is derived from the url by substituting commas for
- * slashes).
- *
- * The qof_session_get_url() routine returns the url that was opened.
- * URL's for local files take the form of
- * file:/some/where/some/file.gml
- */
-const char * qof_session_get_file_path (QofSession *session);
-
-const char * qof_session_get_url (QofSession *session);
-
-/**
- * The qof_session_not_saved() subroutine will return TRUE
- * if any data in the session hasn't been saved to long-term storage.
- */
-gboolean qof_session_not_saved(QofSession *session);
-
-/** FIXME: This isn't as thorough as we might want it to be... */
-gboolean qof_session_save_may_clobber_data (QofSession *session);
-
-/** The qof_session_save() method will commit all changes that have been
- * made to the session. For the file backend, this is nothing
- * more than a write to the file of the current AccountGroup & etc.
- * For the SQL backend, this is typically a no-op (since all data
- * has already been written out to the database.
- */
-void qof_session_save (QofSession *session,
- QofPercentageFunc percentage_func);
-/**
- * The qof_session_end() method will release the session lock. For the
- * file backend, it will *not* save the account group to a file. Thus,
- * this method acts as an "abort" or "rollback" primitive. However,
- * for other backends, such as the sql backend, the data would have
- * been written out before this, and so this routines wouldn't
- * roll-back anything; it would just shut the connection.
- */
-void qof_session_end (QofSession *session);
-
-/** @name Copying entities between sessions.
-
-Only certain backends can cope with selective copying of
-entities and only fully defined QOF entities can be copied
-between sessions - see the \ref QSF (QSF) documentation
-(::qsf_write_file) for more information.
-
-The recommended backend for the new session is QSF or a future
-SQL backend. Using any of these entity copy functions sets a
-flag in the backend that this is now a partial QofBook.
-When you save a session containing a partial QofBook,
-the session will check that the backend is able to handle the
-partial book. If not, the backend will be replaced by one that
-can handle partial books, preferably one using the same
-::access_method. Currently, this means that a book
-using the GnuCash XML v2 file backend will be switched to QSF.
-
-Copied entities are identical to the source entity, all parameters
-defined with ::QofAccessFunc and ::QofSetterFunc in QOF are copied
-and the ::GUID of the original ::QofEntity is set in the new entity.
-Sessions containing copied entities are intended for use
-as mechanisms for data export.
-
-It is acceptable to add entities to new_session in batches. Note that
-any of these calls will fail if an entity already exists in new_session
-with the same GUID as any entity to be copied.
-
-To merge a whole QofBook or where there is any possibility
-of collisions or requirement for user intervention,
-see \ref BookMerge
-
-@{
-
-*/
-
-/** \brief Copy a single QofEntity to another session
-
-Checks first that no entity in the session book contains
-the GUID of the source entity.
-
- @param new_session - the target session
- @param original - the QofEntity* to copy
-
- at return FALSE without copying if the session contains an entity
-with the same GUID already, otherwise TRUE.
-*/
-
-gboolean qof_entity_copy_to_session(QofSession* new_session, QofEntity* original);
-
-/** @brief Copy a GList of entities to another session
-
-The QofBook in the new_session must \b not contain any entities
-with the same GUID as any of the source entities - there is
-no support for handling collisions, instead use \ref BookMerge
-
-Note that the GList (e.g. from ::qof_sql_query_run) can contain
-QofEntity pointers of any ::QofIdType, in any sequence. As long
-as all members of the list are ::QofEntity*, and all GUID's are
-unique, the list can be copied.
-
- @param new_session - the target session
- @param entity_list - a GList of QofEntity pointers of any type(s).
-
- at return FALSE, without copying, if new_session contains any entities
-with the same GUID. Otherwise TRUE.
-
-*/
-gboolean qof_entity_copy_list(QofSession *new_session, GList *entity_list);
-
-/** @brief Copy a QofCollection of entities.
-
-The QofBook in the new_session must \b not contain any entities
-with the same GUID as any entities in the collection - there is
-no support for handling collisions - instead, use \ref BookMerge
-
- at param new_session - the target session
- at param entity_coll - a QofCollection of any QofIdType.
-
- at return FALSE, without copying, if new_session contains any entities
-with the same GUID. Otherwise TRUE.
-*/
-
-gboolean qof_entity_copy_coll(QofSession *new_session, QofCollection *entity_coll);
-
-/** \brief Recursively copy a collection of entities to a session.
-
-\note This function creates a <b>partial QofBook</b>. See
-::qof_entity_copy_to_session for more information.
-
-The QofBook in the new_session must \b not contain any entities
-with the same GUID as any entities to be copied - there is
-no support for handling collisions - instead, use \ref BookMerge
-
-Objects can be defined solely in terms of QOF data types or
-as a mix of data types and other objects, which may in turn
-include other objects. These references can be copied recursively
-down to the third level. e.g. ::GncInvoice refers to ::GncOwner which
-refers to ::GncCustomer which refers to ::GncAddress. See
-::QofEntityReference.
-
-\note This is a deep recursive copy - every referenced entity is copied
-to the new session, including all parameters. The starting point is all
-entities in the top level collection. It can take some time.
-
- at param coll A QofCollection of entities that may or may not have
-references.
-
- at param new_session The QofSession to receive the copied entities.
-
- at return TRUE on success; if any individual copy fails, returns FALSE.
-<b>Note</b> : Some entities may have been copied successfully even if
-one of the references fails to copy.
-
-*/
-gboolean
-qof_entity_copy_coll_r(QofSession *new_session, QofCollection *coll);
-
-/** \brief Recursively copy a single entity to a new session.
-
-Copy the single entity and all referenced entities to the second level.
-
-Only entities that are directly referenced by the top level entity are
-copied.
-
-This is a deep copy - all parameters of all referenced entities are copied. If
-the top level entity has no references, this is identical to
-::qof_entity_copy_to_session.
-
- at param ent A single entity that may or may not have references.
-
- at param new_session The QofSession to receive the copied entities.
-
- at return TRUE on success; if any individual copy fails, returns FALSE.
-<b>Note</b> : Some entities may have been copied successfully even if
-one of the references fails to copy.
-*/
-gboolean
-qof_entity_copy_one_r(QofSession *new_session, QofEntity *ent);
-
-/** @}
-*/
-
-/** @name Using a partial QofBook.
-
-Part of the handling for partial books requires a storage mechanism for
-references to entities that are not within reach of the partial book.
-This requires a GList in the book data to contain the reference
-QofIdType and GUID so that when the book is written out, the
-reference can be included. See ::qof_book_get_data.
-
-When the file is imported back in, the list needs to be rebuilt.
-The QSF backend rebuilds the references by linking to real entities. Other
-backends can process the hash table in similar ways.
-
-The list stores the QofEntityReference to the referenced entity -
-a struct that contains the GUID and the QofIdType of the referenced entity
-as well as the parameter used to obtain the reference.
-
-Partial books need to be differentiated in the backend, the
-flag in the book data is used by qof_session_save to prevent a partial
-book being saved using a backend that requires a full book.
-
- @{ */
-
-
-/** \brief External references in a partial QofBook.
-
-For use by any session that deals with partial QofBooks.
-It is used by the entity copy functions and by the QSF backend.
-Creates a GList stored in the Book hashtable to contain
-repeated references for a single entity.
-*/
-typedef struct qof_entity_reference {
- QofIdType choice_type;/**< When the reference is a different type.*/
- QofIdType type; /**< The type of entity */
- GUID *ref_guid; /**< The GUID of the REFERENCE entity */
- const QofParam *param; /**< The parameter name and type. */
- const GUID *ent_guid; /**< The GUID of the original entity. */
-}QofEntityReference;
-
-/** \brief Get a reference from this entity to another entity.
-
-Used in the preparation of a partial QofBook when the known entity
-(the one currently being copied into the partial book) refers to
-any other entity, usually as a parent or child.
-The routine calls the param_getfcn of the supplied parameter,
-which must return an object (QofEntity*), not a known QOF data type, to
-retrieve the referenced entity and therefore the GUID. The GUID of
-both entities are stored in the reference which then needs to be added
-to the reference list which is added to the partial book data hash.
-The reference itself is used by the backend to preserve the relationship
-between entities within and outside the partial book.
-
-See also ::qof_class_get_referenceList to obtain the list of
-parameters that provide references to the known entity whilst
-excluding parameters that return known QOF data types.
-
-Note that even if the referenced entity \b exists in the partial
-book (or will exist later), a reference must still be obtained and
-added to the reference list for the book itself. This maintains
-the integrity of the partial book during sequential copy operations.
-
- at param ent The known entity.
- at param param The parameter to use to get the referenced entity.
-
- at return FALSE on error, otherwise a pointer to the QofEntityReference.
-*/
-QofEntityReference*
-qof_entity_get_reference_from(QofEntity *ent, const QofParam *param);
-
-/** \brief Adds a new reference to the partial book data hash.
-
-Retrieves any existing reference list and appends the new reference.
-
-If the book is not already marked as partial, it will be marked as partial.
-*/
-void
-qof_session_update_reference_list(QofSession *session, QofEntityReference *reference);
-
-/** Used as the key value for the QofBook data hash.
- *
- * Retrieved later by QSF (or any other suitable backend) to
- * rebuild the references from the QofEntityReference struct
- * that contains the QofIdType and GUID of the referenced entity
- * of the original QofBook as well as the parameter data and the
- * GUID of the original entity.
- * */
-#define ENTITYREFERENCE "QofEntityReference"
-
-/** \brief Flag indicating a partial QofBook.
-
-When set in the book data with a gboolean value of TRUE,
-the flag denotes that only a backend that supports partial
-books can be used to save this session.
-*/
-
-#define PARTIAL_QOFBOOK "PartialQofBook"
-
-/** @}
-*/
-
-/** \brief Allow session data to be printed to stdout
-
-book_id can't be NULL and we do need to have an access_method,
-so use one to solve the other.
-
-To print a session to stdout, use ::qof_session_begin. Example:
-
-\a qof_session_begin(session,QOF_STDOUT,TRUE,FALSE);
-
-When you call qof_session_save(session, NULL), the output will appear
-on stdout and can be piped or redirected to other processes.
-
-Currently, only the QSF backend supports writing to stdout, other
-backends may return a ::QofBackendError.
-*/
-#define QOF_STDOUT "file:"
-
-/** @name Event Handling
-
- @{ */
-/** The qof_session_events_pending() method will return TRUE if the backend
- * has pending events which must be processed to bring the engine
- * up to date with the backend.
- */
-gboolean qof_session_events_pending (QofSession *session);
-
-/** The qof_session_process_events() method will process any events indicated
- * by the qof_session_events_pending() method. It returns TRUE if the
- * engine was modified while engine events were suspended.
- */
-gboolean qof_session_process_events (QofSession *session);
-/** @} */
-
-#ifdef GNUCASH_MAJOR_VERSION
-/** Run the RPC Server
- * @deprecated will go away */
-void gnc_run_rpc_server (void);
-
-/** XXX session_export really doesn't belong here .
- * This functino exports the list of accounts to a file. Its a stop-gap
- * measure until full book-closing is implemented.
- */
-gboolean qof_session_export (QofSession *tmp_session,
- QofSession *real_session,
- QofPercentageFunc percentage_func);
-
-#endif /* GNUCASH_MAJOR_VERSION */
-
-/** Register a function to be called just before a session is closed.
- *
- * @param fn The function to be called. The function definition must
- * be func(gpointer session, gpointer user_data);
- *
- * @param data The data to be passed to the function. */
-void qof_session_add_close_hook (GFunc fn, gpointer data);
-
-/** Call all registered session close hooks, informing them that the
- * specified session is about to be closed.
- *
- * @param session A pointer to the session being closed. */
-void qof_session_call_close_hooks (QofSession *session);
-
-#endif /* QOF_SESSION_H */
-/** @} */
Deleted: gnucash/trunk/src/engine/qofsql.c
===================================================================
--- gnucash/trunk/src/engine/qofsql.c 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofsql.c 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,928 +0,0 @@
-/********************************************************************\
- * qofsql.c -- QOF client-side SQL parser *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-/**
- @file qofsql.c
- @brief QOF client-side SQL parser.
- @author Copyright (C) 2004 Linas Vepstas <linas at linas.org>
-
-*/
-#define _GNU_SOURCE
-
-#include <stdlib.h> /* for working atoll */
-#include <errno.h>
-#include "glib.h"
-#include "config.h"
-#ifdef HAVE_GDA
-#include <sql/sql_parser.h>
-#else
-#include "sql_parser.h"
-#endif
-#include <time.h>
-#include "kvp_frame.h"
-#include "gnc-date.h"
-#include "gnc-numeric.h"
-#include "gnc-trace.h"
-#include "guid.h"
-#include "qofbook.h"
-#include "qofquery.h"
-#include "qofquerycore.h"
-#include "qofsql.h"
-#include "gnc-engine-util.h"
-#include "qofinstance-p.h"
-#include "qofobject.h"
-
-static QofLogModule log_module = QOF_MOD_QUERY;
-
-/* =================================================================== */
-
-struct _QofSqlQuery
-{
- sql_statement *parse_result;
- QofQuery *qof_query;
- QofBook *book;
- char * single_global_tablename;
- KvpFrame *kvp_join;
- GList *param_list;
- QofEntity *inserted_entity;
-};
-
-/* ========================================================== */
-
-QofSqlQuery *
-qof_sql_query_new(void)
-{
- QofSqlQuery * sqn = (QofSqlQuery *) g_new0 (QofSqlQuery, 1);
-
- sqn->qof_query = NULL;
- sqn->parse_result = NULL;
- sqn->book = NULL;
- sqn->single_global_tablename = NULL;
- sqn->kvp_join = NULL;
-
- return sqn;
-}
-
-/* ========================================================== */
-
-void
-qof_sql_query_destroy (QofSqlQuery *q)
-{
- if (!q) return;
- qof_query_destroy (q->qof_query);
- sql_destroy (q->parse_result);
- g_free (q);
-}
-
-/* ========================================================== */
-
-QofQuery *
-qof_sql_query_get_query (QofSqlQuery *q)
-{
- if (!q) return NULL;
- return q->qof_query;
-}
-
-/* ========================================================== */
-
-void
-qof_sql_query_set_book (QofSqlQuery *q, QofBook *book)
-{
- if (!q) return;
- q->book = book;
-}
-
-/* ========================================================== */
-
-void
-qof_sql_query_set_kvp (QofSqlQuery *q, KvpFrame *kvp)
-{
- if (!q) return;
- q->kvp_join = kvp;
-}
-
-/* ========================================================== */
-
-static inline void
-get_table_and_param (char * str, char **tab, char **param)
-{
- char * end = strchr (str, '.');
- if (!end)
- {
- *tab = 0;
- *param = str;
- return;
- }
- *end = 0;
- *tab = str;
- *param = end+1;
-}
-
-static inline char *
-dequote_string (char *str)
-{
- size_t len;
- /* strip out quotation marks ... */
- if (('\'' == str[0]) ||
- ('\"' == str[0]))
- {
- str ++;
- len = strlen(str);
- str[len-1] = 0;
- }
- return str;
-}
-
-static QofQuery *
-handle_single_condition (QofSqlQuery *query, sql_condition * cond)
-{
- char tmpbuff[128];
- GSList *param_list;
- GList *guid_list;
- QofQueryPredData *pred_data;
- sql_field_item *sparam, *svalue;
- char * qparam_name, *qvalue_name, *table_name, *param_name;
- char *sep, *path,*str,*p;
- QofQuery *qq;
- KvpValue *kv, *kval;
- KvpValueType kvt;
- QofQueryCompare qop;
- time_t exact;
- int rc, len;
- Timespec ts;
- QofType param_type;
- QofGuidMatch gm;
-
- pred_data = NULL;
- if (NULL == cond)
- {
- PWARN("missing condition");
- return NULL;
- }
- /* -------------------------------- */
- /* field to match, assumed, for now to be on the left */
- /* XXX fix this so it can be either left or right */
- if (NULL == cond->d.pair.left)
- {
- PWARN("missing left parameter");
- return NULL;
- }
- sparam = cond->d.pair.left->item;
- if (SQL_name != sparam->type)
- {
- PWARN("we support only parameter names at this time (parsed %d)",
- sparam->type);
- return NULL;
- }
- qparam_name = sparam->d.name->data;
- if (NULL == qparam_name)
- {
- PWARN ("missing parameter name");
- return NULL;
- }
-
- /* -------------------------------- */
- /* value to match, assumed, for now, to be on the right. */
- /* XXX fix this so it can be either left or right */
- if (NULL == cond->d.pair.right)
- {
- PWARN ("missing right parameter");
- return NULL;
- }
- svalue = cond->d.pair.right->item;
- if (SQL_name != svalue->type)
- {
- PWARN("we support only simple values (parsed as %d)", svalue->type);
- return NULL;
- }
- qvalue_name = svalue->d.name->data;
- if (NULL == qvalue_name)
- {
- PWARN("missing value");
- return NULL;
- }
- qvalue_name = dequote_string (qvalue_name);
- qvalue_name = (char *) qof_util_whitespace_filter (qvalue_name);
-
- /* Look to see if its the special KVP value holder.
- * If it is, look up the value. */
- if (0 == strncasecmp (qvalue_name, "kvp://", 6))
- {
- if (NULL == query->kvp_join)
- {
- PWARN ("missing kvp frame");
- return NULL;
- }
- kv = kvp_frame_get_value (query->kvp_join, qvalue_name+5);
- /* If there's no value, its not an error;
- * we just don't do this predicate */
- if (!kv) return NULL;
- kvt = kvp_value_get_type (kv);
-
- tmpbuff[0] = 0x0;
- qvalue_name = tmpbuff;
- switch (kvt)
- {
- case KVP_TYPE_GINT64:
- {
- gint64 ival = kvp_value_get_gint64(kv);
- sprintf (tmpbuff, "%" G_GINT64_FORMAT "\n", ival);
- break;
- }
- case KVP_TYPE_DOUBLE:
- {
- double ival = kvp_value_get_double(kv);
- sprintf (tmpbuff, "%26.18g\n", ival);
- break;
- }
- case KVP_TYPE_STRING:
- /* If there's no value, its not an error;
- * we just don't do this predicate */
- qvalue_name = kvp_value_get_string (kv);
- if (!qvalue_name) return NULL;
- break;
- case KVP_TYPE_GUID:
- case KVP_TYPE_TIMESPEC:
- case KVP_TYPE_BINARY:
- case KVP_TYPE_GLIST:
- case KVP_TYPE_NUMERIC:
- case KVP_TYPE_FRAME:
- PWARN ("unhandled kvp type=%d", kvt);
- return NULL;
- }
- }
-
- /* -------------------------------- */
- /* Now start building the QOF parameter */
- param_list = qof_query_build_param_list (qparam_name, NULL);
-
- /* Get the where-term comparison operator */
- switch (cond->op)
- {
- case SQL_eq: qop = QOF_COMPARE_EQUAL; break;
- case SQL_gt: qop = QOF_COMPARE_GT; break;
- case SQL_lt: qop = QOF_COMPARE_LT; break;
- case SQL_geq: qop = QOF_COMPARE_GTE; break;
- case SQL_leq: qop = QOF_COMPARE_LTE; break;
- case SQL_diff: qop = QOF_COMPARE_NEQ; break;
- default:
- /* XXX for string-type queries, we should be able to
- * support 'IN' for substring search. Also regex. */
- PWARN ("Unsupported compare op (parsed as %u)", cond->op);
- return NULL;
- }
-
- /* OK, need to know the type of the thing being matched
- * in order to build the correct predicate. Get the type
- * from the object parameters. */
- get_table_and_param (qparam_name, &table_name, ¶m_name);
- if (NULL == table_name)
- {
- table_name = query->single_global_tablename;
- }
- if (NULL == table_name)
- {
- PWARN ("Need to specify an object class to query");
- return NULL;
- }
-
- if (FALSE == qof_class_is_registered (table_name))
- {
- PWARN ("The query object \'%s\' is not known", table_name);
- return NULL;
- }
-
- param_type = qof_class_get_parameter_type (table_name, param_name);
- if (!param_type)
- {
- PWARN ("The parameter \'%s\' on object \'%s\' is not known",
- param_name, table_name);
- return NULL;
- }
-
- if (!strcmp (param_type, QOF_TYPE_STRING))
- {
- pred_data =
- qof_query_string_predicate (qop, /* comparison to make */
- qvalue_name, /* string to match */
- QOF_STRING_MATCH_CASEINSENSITIVE, /* case matching */
- FALSE); /* use_regexp */
- }
- else if (!strcmp (param_type, QOF_TYPE_CHAR))
- {
- QofCharMatch cm = QOF_CHAR_MATCH_ANY;
- if (QOF_COMPARE_NEQ == qop) cm = QOF_CHAR_MATCH_NONE;
- pred_data = qof_query_char_predicate (cm, qvalue_name);
- }
- else if (!strcmp (param_type, QOF_TYPE_INT32))
- {
- gint32 ival = atoi (qvalue_name);
- pred_data = qof_query_int32_predicate (qop, ival);
- }
- else if (!strcmp (param_type, QOF_TYPE_INT64))
- {
- gint64 ival = atoll (qvalue_name);
- pred_data = qof_query_int64_predicate (qop, ival);
- }
- else if (!strcmp (param_type, QOF_TYPE_DOUBLE))
- {
- double ival = atof (qvalue_name);
- pred_data = qof_query_double_predicate (qop, ival);
- }
- else if (!strcmp (param_type, QOF_TYPE_BOOLEAN))
- {
- gboolean ival = qof_util_bool_to_int (qvalue_name);
- pred_data = qof_query_boolean_predicate (qop, ival);
- }
- else if (!strcmp (param_type, QOF_TYPE_DATE))
- {
- /* Use a timezone independent setting */
- qof_date_format_set(QOF_DATE_FORMAT_UTC);
- rc = 0;
- if(FALSE == qof_scan_date_secs (qvalue_name, &exact))
- {
- char *tail;
- exact = strtoll(qvalue_name, &tail, 0);
-// PWARN ("unable to parse date: %s", qvalue_name);
-// return NULL;
- }
- ts.tv_sec = exact;
- ts.tv_nsec = 0;
- pred_data = qof_query_date_predicate (qop, QOF_DATE_MATCH_NORMAL, ts);
- }
- else if (!strcmp (param_type, QOF_TYPE_NUMERIC))
- {
- gnc_numeric ival;
- string_to_gnc_numeric (qvalue_name, &ival);
- pred_data = qof_query_numeric_predicate (qop, QOF_NUMERIC_MATCH_ANY, ival);
- }
- else if (!strcmp (param_type, QOF_TYPE_DEBCRED))
- {
- // XXX this probably needs some work ...
- gnc_numeric ival;
- string_to_gnc_numeric (qvalue_name, &ival);
- pred_data = qof_query_numeric_predicate (qop, QOF_NUMERIC_MATCH_ANY, ival);
- }
- else if (!strcmp (param_type, QOF_TYPE_GUID))
- {
- GUID guid;
- gboolean rc = string_to_guid (qvalue_name, &guid);
- if (0 == rc)
- {
- PWARN ("unable to parse guid: %s", qvalue_name);
- return NULL;
- }
-
- // XXX less, than greater than don't make sense,
- // should check for those bad conditions
-
- gm = QOF_GUID_MATCH_ANY;
- if (QOF_COMPARE_NEQ == qop) gm = QOF_GUID_MATCH_NONE;
- guid_list = g_list_append (NULL, &guid);
- pred_data = qof_query_guid_predicate (gm, guid_list);
-
- g_list_free (guid_list);
- }
- else if (!strcmp (param_type, QOF_TYPE_KVP))
- {
- /* We are expecting an encoded value that looks like
- * /some/path/string:value
- */
- sep = strchr (qvalue_name, ':');
- if (!sep) return NULL;
- *sep = 0;
- path = qvalue_name;
- str = sep +1;
- /* If str has only digits, we know its a plain number.
- * If its numbers and a decimal point, assume a float
- * If its numbers and a slash, assume numeric
- * If its 32 bytes of hex, assume GUID
- * If it looks like an iso date ...
- * else assume its a string.
- */
- kval = NULL;
- len = strlen (str);
- if ((32 == len) && (32 == strspn (str, "0123456789abcdef")))
- {
- GUID guid;
- string_to_guid (str, &guid);
- kval = kvp_value_new_guid (&guid);
- }
- else
- if (len == strspn (str, "0123456789"))
- {
- kval = kvp_value_new_gint64 (atoll(str));
- }
- else
- if ((p=strchr (str, '.')) &&
- ((len-1) == (strspn (str, "0123456789") +
- strspn (p+1, "0123456789"))))
- {
- kval = kvp_value_new_double (atof(str));
- }
-
- else
- if ((p=strchr (str, '/')) &&
- ((len-1) == (strspn (str, "0123456789") +
- strspn (p+1, "0123456789"))))
- {
- gnc_numeric num;
- string_to_gnc_numeric (str, &num);
- kval = kvp_value_new_gnc_numeric (num);
- }
- else
- if ((p=strchr (str, '-')) &&
- (p=strchr (p+1, '-')) &&
- (p=strchr (p+1, ' ')) &&
- (p=strchr (p+1, ':')) &&
- (p=strchr (p+1, ':')))
- {
- kval = kvp_value_new_timespec (gnc_iso8601_to_timespec_gmt(str));
- }
-
- /* The default handler is a string */
- if (NULL == kval)
- {
- kval = kvp_value_new_string (str);
- }
- pred_data = qof_query_kvp_predicate_path (qop, path, kval);
- }
- else
- {
- PWARN ("The predicate type \"%s\" is unsupported for now", param_type);
- return NULL;
- }
-
- qq = qof_query_create();
- qof_query_add_term (qq, param_list, pred_data, QOF_QUERY_FIRST_TERM);
- return qq;
-}
-
-/* ========================================================== */
-
-static QofQuery *
-handle_where (QofSqlQuery *query, sql_where *swear)
-{
- QofQueryOp qop;
- QofQuery * qq;
-
- switch (swear->type)
- {
- case SQL_pair:
- {
- QofQuery *qleft = handle_where (query, swear->d.pair.left);
- QofQuery *qright = handle_where (query, swear->d.pair.right);
- if (NULL == qleft) return qright;
- if (NULL == qright) return qleft;
- switch (swear->d.pair.op)
- {
- case SQL_and: qop = QOF_QUERY_AND; break;
- case SQL_or: qop = QOF_QUERY_OR; break;
- /* XXX should add support for nand, nor, xor */
- default:
- qof_query_destroy (qleft);
- qof_query_destroy (qright);
- return NULL;
- }
- qq = qof_query_merge (qleft, qright, qop);
- qof_query_destroy (qleft);
- qof_query_destroy (qright);
- return qq;
- }
- case SQL_negated:
- {
- QofQuery *qq = handle_where (query, swear->d.negated);
- QofQuery *qneg = qof_query_invert (qq);
- qof_query_destroy (qq);
- return qneg;
- }
-
- case SQL_single:
- {
- sql_condition * cond = swear->d.single;
- return handle_single_condition (query, cond);
- }
- }
- return NULL;
-}
-
-/* ========================================================== */
-
-static void
-handle_sort_order (QofSqlQuery *query, GList *sorder_list)
-{
- GSList *qsp[3];
- GList *n;
- gboolean direction[3];
- int i;
- sql_order_field *sorder;
- char * qparam_name;
-
- if (!sorder_list) return;
-
- for (i=0; i<3; i++)
- {
- qsp[i] = NULL;
- direction[i] = 0;
-
- if (sorder_list)
- {
- sorder = sorder_list->data;
-
- /* Set the sort direction */
- if (SQL_asc == sorder->order_type) direction[i] = TRUE;
-
- /* Find the parameter name */
- qparam_name = NULL;
- n = sorder->name;
- if (n)
- {
- qparam_name = n->data;
- if (qparam_name)
- {
- qsp[i] = qof_query_build_param_list (qparam_name, NULL);
- }
- n = n->next; /* next parameter */
- }
- else
- {
- /* if no next parameter, then next order-by */
- sorder_list = sorder_list->next;
- }
- }
- }
-
- qof_query_set_sort_order (query->qof_query, qsp[0], qsp[1], qsp[2]);
- qof_query_set_sort_increasing (query->qof_query, direction[0],
- direction[1], direction[2]);
-}
-
-/* ========================================================== */
-static void
-qof_queryForeachParam( QofParam* param, gpointer user_data)
-{
- QofSqlQuery *q;
-
- g_return_if_fail(user_data != NULL);
- q = (QofSqlQuery*)user_data;
- g_return_if_fail(param != NULL);
- if((param->param_getfcn != NULL)&&(param->param_setfcn != NULL)) {
- q->param_list = g_list_append(q->param_list, param);
- }
-}
-
-static const char*
-qof_sql_get_value(sql_insert_statement *insert)
-{
- GList *walk, *cur;
- const char *insert_string;
- sql_field *field;
- sql_field_item * item;
-
- /* how to cope with multiple results? */
- if (insert->values == NULL) { return NULL; }
- insert_string = NULL;
- for (walk = insert->values; walk != NULL; walk = walk->next)
- {
- field = walk->data;
- item = field->item;
- for (cur = item->d.name; cur != NULL; cur = cur->next)
- {
- insert_string = g_strdup_printf("%s", (char*)cur->data);
- }
- }
- return insert_string;
-}
-
-static const QofParam*
-qof_sql_get_param(QofIdTypeConst type, sql_insert_statement *insert)
-{
- GList *walk, *cur;
- const char *param_name;
- const QofParam *param;
- sql_field *field;
- sql_field_item *item;
-
- param = NULL;
- param_name = NULL;
- if (insert->fields == NULL) { return NULL; }
- for (walk = insert->fields; walk != NULL; walk = walk->next)
- {
- field = walk->data;
- item = field->item;
- for (cur = item->d.name; cur != NULL; cur = cur->next)
- {
- param_name = g_strdup_printf("%s", (char*)cur->data);
- }
- }
- param = qof_class_get_parameter(type, param_name);
- return param;
-}
-
-static void
-qof_sql_insertCB( gpointer value, gpointer data)
-{
- GList *param_list;
- QofSqlQuery *q;
- QofIdTypeConst type;
- sql_insert_statement *sis;
- const char *insert_string;
- gboolean registered_type;
- QofEntity *ent;
- QofParam *param;
- struct tm query_time;
- time_t query_time_t;
- /* cm_ prefix used for variables that hold the data to commit */
- gnc_numeric cm_numeric;
- double cm_double;
- gboolean cm_boolean;
- gint32 cm_i32;
- gint64 cm_i64;
- Timespec cm_date;
- char cm_char, *tail;
- GUID *cm_guid;
-/* KvpFrame *cm_kvp;
- KvpValue *cm_value;
- KvpValueType cm_type;*/
- const QofParam *cm_param;
- void (*string_setter) (QofEntity*, const char*);
- void (*date_setter) (QofEntity*, Timespec);
- void (*numeric_setter) (QofEntity*, gnc_numeric);
- void (*double_setter) (QofEntity*, double);
- void (*boolean_setter) (QofEntity*, gboolean);
- void (*i32_setter) (QofEntity*, gint32);
- void (*i64_setter) (QofEntity*, gint64);
- void (*char_setter) (QofEntity*, char);
-/* void (*kvp_frame_setter) (QofEntity*, KvpFrame*);*/
-
- q = (QofSqlQuery*)data;
- ent = q->inserted_entity;
- param = (QofParam*)value;
- sis = q->parse_result->statement;
- type = g_strdup_printf("%s", sis->table->d.simple);
- insert_string = g_strdup(qof_sql_get_value(sis));
- cm_param = qof_sql_get_param(type, sis);
- param_list = g_list_copy(q->param_list);
- while(param_list != NULL) {
- if(safe_strcmp(cm_param->param_type, QOF_TYPE_STRING) == 0) {
- string_setter = (void(*)(QofEntity*, const char*))cm_param->param_setfcn;
- if(string_setter != NULL) { string_setter(ent, insert_string); }
- registered_type = TRUE;
- }
- if(safe_strcmp(cm_param->param_type, QOF_TYPE_DATE) == 0) {
- date_setter = (void(*)(QofEntity*, Timespec))cm_param->param_setfcn;
- strptime(insert_string, QOF_UTC_DATE_FORMAT, &query_time);
- query_time_t = mktime(&query_time);
- timespecFromTime_t(&cm_date, query_time_t);
- if(date_setter != NULL) { date_setter(ent, cm_date); }
- }
- if((safe_strcmp(cm_param->param_type, QOF_TYPE_NUMERIC) == 0) ||
- (safe_strcmp(cm_param->param_type, QOF_TYPE_DEBCRED) == 0)) {
- numeric_setter = (void(*)(QofEntity*, gnc_numeric))cm_param->param_setfcn;
- string_to_gnc_numeric(insert_string, &cm_numeric);
- if(numeric_setter != NULL) { numeric_setter(ent, cm_numeric); }
- }
- if(safe_strcmp(cm_param->param_type, QOF_TYPE_GUID) == 0) {
- cm_guid = g_new(GUID, 1);
- if(TRUE != string_to_guid(insert_string, cm_guid))
- {
- LEAVE (" string to guid failed for %s", insert_string);
- return;
- }
-/* reference_type = xmlGetProp(node, QSF_OBJECT_TYPE);
- if(0 == safe_strcmp(QOF_PARAM_GUID, reference_type))
- {
- qof_entity_set_guid(qsf_ent, cm_guid);
- }
- else {
- reference = qof_entity_get_reference_from(qsf_ent, cm_param);
- if(reference) {
- params->referenceList = g_list_append(params->referenceList, reference);
- }
- }*/
- }
- if(safe_strcmp(cm_param->param_type, QOF_TYPE_INT32) == 0) {
- errno = 0;
- cm_i32 = (gint32)strtol (insert_string, &tail, 0);
- if(errno == 0) {
- i32_setter = (void(*)(QofEntity*, gint32))cm_param->param_setfcn;
- if(i32_setter != NULL) { i32_setter(ent, cm_i32); }
- }
-// else { qof_backend_set_error(params->be, ERR_QSF_OVERFLOW); }
- }
- if(safe_strcmp(cm_param->param_type, QOF_TYPE_INT64) == 0) {
- errno = 0;
- cm_i64 = strtoll(insert_string, &tail, 0);
- if(errno == 0) {
- i64_setter = (void(*)(QofEntity*, gint64))cm_param->param_setfcn;
- if(i64_setter != NULL) { i64_setter(ent, cm_i64); }
- }
-// else { qof_backend_set_error(params->be, ERR_QSF_OVERFLOW); }
- }
- if(safe_strcmp(cm_param->param_type, QOF_TYPE_DOUBLE) == 0) {
- errno = 0;
- cm_double = strtod(insert_string, &tail);
- if(errno == 0) {
- double_setter = (void(*)(QofEntity*, double))cm_param->param_setfcn;
- if(double_setter != NULL) { double_setter(ent, cm_double); }
- }
- }
- if(safe_strcmp(cm_param->param_type, QOF_TYPE_BOOLEAN) == 0){
- if(0 == safe_strcmp(insert_string, "TRUE")) {
- cm_boolean = TRUE;
- }
- else { cm_boolean = FALSE; }
- boolean_setter = (void(*)(QofEntity*, gboolean))cm_param->param_setfcn;
- if(boolean_setter != NULL) { boolean_setter(ent, cm_boolean); }
- }
- if(safe_strcmp(cm_param->param_type, QOF_TYPE_KVP) == 0) {
-
- }
- if(safe_strcmp(cm_param->param_type, QOF_TYPE_CHAR) == 0) {
- cm_char = *insert_string;
- char_setter = (void(*)(QofEntity*, char))cm_param->param_setfcn;
- if(char_setter != NULL) { char_setter(ent, cm_char); }
- }
- param_list = param_list->next;
- }
-}
-
-static QofEntity*
-qof_query_insert(QofSqlQuery *query)
-{
- QofIdType type;
- QofInstance *inst;
- sql_insert_statement *sis;
- sql_table *sis_t;
-
- query->param_list = NULL;
- type = NULL;
- sis = query->parse_result->statement;
- switch(sis->table->type) {
- case SQL_simple: {
- sis_t = sis->table;
- query->single_global_tablename = g_strdup_printf("%s", sis_t->d.simple);
- type = g_strdup(query->single_global_tablename);
- break;
- }
- default: {
- fprintf(stderr, "default");
- }
- }
- inst = (QofInstance*)qof_object_new_instance(type, query->book);
- if(inst == NULL) { return NULL; }
- query->param_list = NULL;
- query->inserted_entity = &inst->entity;
- qof_class_param_foreach((QofIdTypeConst)type, qof_queryForeachParam, query);
- g_list_foreach(query->param_list, qof_sql_insertCB, query);
- return query->inserted_entity;
-}
-
-static const char*
-sql_type_as_string(sql_statement_type type)
-{
- switch (type)
- {
- case SQL_select : { return "SELECT"; }
- case SQL_insert : { return "INSERT"; }
- case SQL_delete : { return "DELETE"; }
- case SQL_update : { return "UPDATE"; }
- default : { return "unknown"; }
- }
-}
-
-void
-qof_sql_query_parse (QofSqlQuery *query, const char *str)
-{
- GList *tables;
- char *buf;
- sql_select_statement *sss;
- sql_where *swear;
-
- if (!query) return;
-
- /* Delete old query, if any */
- if (query->qof_query)
- {
- qof_query_destroy (query->qof_query);
- sql_destroy(query->parse_result);
- query->qof_query = NULL;
- }
-
- /* Parse the SQL string */
- buf = g_strdup(str);
- query->parse_result = sql_parse (buf);
- g_free(buf);
-
- if (!query->parse_result)
- {
- PWARN ("parse error");
- return;
- }
-
- if ((SQL_select != query->parse_result->type)&&(SQL_insert != query->parse_result->type))
- {
- PWARN("currently, only SELECT or INSERT statements are supported, "
- "got type=%s", sql_type_as_string(query->parse_result->type));
- return;
- }
-
- /* If the user wrote "SELECT * FROM tablename WHERE ..."
- * then we have a single global tablename. But if the
- * user wrote "SELECT * FROM tableA, tableB WHERE ..."
- * then we don't have a single unique table-name.
- */
- tables = sql_statement_get_tables (query->parse_result);
- if (1 == g_list_length (tables))
- {
- query->single_global_tablename = tables->data;
- }
- /* if this is an insert, we're done with the parse. */
- if(SQL_insert == query->parse_result->type) {
- query->qof_query = qof_query_create();
- return;
- }
- sss = query->parse_result->statement;
- swear = sss->where;
- if (swear)
- {
- /* Walk over the where terms, turn them into QOF predicates */
- query->qof_query = handle_where (query, swear);
- if (NULL == query->qof_query) return;
- }
- else
- {
- query->qof_query = qof_query_create();
- }
- /* Provide support for different sort orders */
- handle_sort_order (query, sss->order);
-
- /* We also want to set the type of thing to search for.
- * If the user said SELECT * FROM ... then we should return
- * a list of QofEntity. Otherwise, we return ... ?
- * XXX all this needs fixing.
- */
- qof_query_search_for (query->qof_query, query->single_global_tablename);
-}
-
-/* ========================================================== */
-
-GList *
-qof_sql_query_run (QofSqlQuery *query, const char *str)
-{
- GList *results;
-
- if (!query) return NULL;
-
- qof_sql_query_parse (query, str);
- if (NULL == query->qof_query) return NULL;
-
- qof_query_set_book (query->qof_query, query->book);
- if(SQL_insert == query->parse_result->type){
- results = NULL;
- results = g_list_append(results, qof_query_insert(query));
- return results;
- }
- qof_query_print (query->qof_query);
- results = qof_query_run (query->qof_query);
-
- return results;
-}
-
-GList *
-qof_sql_query_rerun (QofSqlQuery *query)
-{
- GList *results;
-
- if (!query) return NULL;
-
- if (NULL == query->qof_query) return NULL;
-
- qof_query_set_book (query->qof_query, query->book);
-
- // qof_query_print (query->qof_query);
- results = qof_query_run (query->qof_query);
-
- return results;
-}
-
-/* ========================== END OF FILE =================== */
Deleted: gnucash/trunk/src/engine/qofsql.h
===================================================================
--- gnucash/trunk/src/engine/qofsql.h 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/engine/qofsql.h 2005-11-13 13:22:34 UTC (rev 11917)
@@ -1,201 +0,0 @@
-/********************************************************************\
- * qofsql.h -- QOF client-side SQL parser *
- * *
- * 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 *
- * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
- * Boston, MA 02111-1307, USA gnu at gnu.org *
- * *
-\********************************************************************/
-
-/** @addtogroup Query
-@{ */
-/**
- @file qofsql.h
- @brief QOF client-side SQL parser.
- @author Copyright (C) 2004 Linas Vepstas <linas at linas.org>
-*/
-
-#ifndef QOF_SQL_QUERY_H
-#define QOF_SQL_QUERY_H
-
-#include <glib.h>
-#include <kvp_frame.h>
-#include <qofbook.h>
-#include <qofquery.h>
-
-/** @addtogroup SQL SQL Interface to Query
-
-The types of SQL queries that are allowed at this point are very
-limited. In general, only the following types of queries are
-supported:
- SELECT * FROM SomeObj WHERE (param_a < 10.0) AND (param_b = "asdf")
- SORT BY param_c DESC;
- INSERT INTO SomeObj (param_a, param_b, param_c) VALUES
- ("value_a", true, "0/1");
-
-For SELECT, the returned list is a list of all of the instances of 'SomeObj' that
-match the query. The 'SORT' term is optional. The 'WHERE' term is
-optional; but if you don't include 'WHERE', you will get a list of
-all of the object instances. The Boolean operations 'AND' and 'OR'
-together with parenthesis can be used to construct arbitrarily
-nested predicates.
-
-For INSERT, the returned list is a list containing the newly created instance
-of 'SomeObj'.
-
-Joins are not supported directly.
- SELECT * FROM ObjA,ObjB WHERE (ObjA.param_id = ObjB.param_other_id);
-The problem with the above is that the search requires a nested
-search loop, aka a 'join', which is not currently supported in the
-underlying QofQuery code.
-
-However, by repeating queries and adding the entities to a new session using
-::qof_entity_copy_list, a series of queries can be added to a single
-book. e.g. You can insert multiple entities and save out as a QSF XML
-file or use multiple SELECT queries to build a precise list - this
-can be used to replicate most of the functionality of a SQL join.
-
-SELECT * from ObjA where param_id = value;
-SELECT * from ObjB where param_other_id = value;
-
-Equivalent to:
-SELECT * from ObjA,ObjB where param_id = param_other_id and param_id = value;
-
-When combined with a foreach callback on the value of param_id for each
-entity in the QofBook, you can produce the effect of a join from running
-the two SELECT queries for each value of param_id held in 'value'.
-
-See ::QofEntityForeachCB and ::qof_object_foreach.
-
-Date queries handle full date and time strings, using the format
-exported by the QSF backend. To query dates and times, convert
-user input into UTC time using the ::QOF_UTC_DATE_FORMAT string.
-e.g. set the UTC date format and call ::qof_print_time_buff
-with a time_t obtained via ::timespecToTime_t.
-
-If the param is a KVP frame, then we use a special markup to
-indicate frame values. The markup should look like
-/some/kvp/path:value. Thus, for example,
- SELECT * FROM SomeObj WHERE (param_a < '/some/kvp:10.0')
-will search for the object where param_a is a KVP frame, and this
-KVP frame contains a path '/some/kvp' and the value stored at that
-path is floating-point and that float value is less than 10.0.
-
-The following are types of queries are NOT supported:
- SELECT a,b,c FROM ...
-I am thinking of implementing the above as a list of KVP's
-whose keys would be a,b,c and values would be the results of the
-search. (Linas)
-
-XXX (Neil W). Alternatively, I need to use something like this
-when converting QOF objects between applications by using the
-returned parameter values to create a second object. One application
-using QOF could register objects from two applications and convert
-data from one to the other by using SELECT a,b,c FROM ObjA;
-SELECT d,f,k FROM ObjB; qof_object_new_instance(); ObjC_set_a(value_c);
-ObjC_set_b(value_k) etc. What's needed is for the SELECT to return
-a complete object that only contains the parameters selected.
-
- Also unsupported: UPDATE.
-
-Certain SQL commands can have no QOF equivalent and will
-generate a runtime parser error:
- - ALTER
- - CREATE
- - DROP
- - FLUSH
- - GRANT
- - KILL
- - LOCK
- - OPTIMIZE
- - REVOKE
- - USE
-
- @{ */
-typedef struct _QofSqlQuery QofSqlQuery;
-
-/** Create a new SQL-syntax query machine.
- */
-QofSqlQuery * qof_sql_query_new (void);
-void qof_sql_query_destroy (QofSqlQuery *);
-
-/** Set the book to be searched (you can search multiple books)
- * If no books are set, no results will be returned (since there
- * is nothing to search over).
- */
-void qof_sql_query_set_book (QofSqlQuery *q, QofBook *book);
-
-/** \brief Perform the query, return the results.
-
- * The book must be set in order to be able to perform a query.
- *
- * The returned list will have been sorted using the indicated sort
- * order, (by default ascending order) and trimmed to the
- * max_results length.
- * Do NOT free the resulting list. This list is managed internally
- * by QofSqlQuery.
- *
- */
-
-GList * qof_sql_query_run (QofSqlQuery *query, const char * str);
-
-/** Same ::qof_sql_query_run, but just parse/pre-process the query; do
- not actually run it over the dataset. The QofBook does not
- need to be set before calling this function.
-*/
-
-void qof_sql_query_parse (QofSqlQuery *query, const char * str);
-
-/** Return the QofQuery form of the previously parsed query. */
-QofQuery * qof_sql_query_get_query (QofSqlQuery *);
-
-/** Run the previously parsed query. The QofBook must be set
- * before this function can be called. Note, teh QofBook can
- * be changed between each successive call to this routine.
- * This routine can be called after either qof_sql_query_parse()
- * or qof_sql_query_run() because both will set up the parse.
- */
-GList * qof_sql_query_rerun (QofSqlQuery *query);
-
-/**
- * Set the kvp frame to be used for formulating 'indirect' predicates.
- *
- * Although joins are not supported (see above), there is one special
- * hack that one can use to pass data indirectly into the predicates.
- * This is by using a KVP key name to reference the value to be used
- * for a predicate. Thus, for example,
- * SELECT * FROM SomeObj WHERE (param_a = KVP:/some/key/path);
- * will look up the value stored at '/some/key/path', and use that
- * value to form the actual predicate. So, for example, if
- * the value stored at '/some/key/path' was 2, then the actual
- * query run will be
- * SELECT * FROM SomeObj WHERE (param_a = 2);
- * The lookup occurs at the time that the query is formulated.
- *
- * The query does *not* take over ownership of the kvp frame,
- * nor does it copy it. Thus, the kvp frame must exist when the
- * query is formulated, and it is the responsibility of the
- * caller to free it when no longer needed.
- *
- * Note that because this feature is a kind of a hack put in place
- * due to the lack of support for joins, it will probably go away
- * (be deprecated) if/when joins are implemented.
- */
-void qof_sql_query_set_kvp (QofSqlQuery *, KvpFrame *);
-
-/** @} */
-#endif /* QOF_SQL_QUERY_H */
-/** @} */
Modified: gnucash/trunk/src/gnome-utils/test/Makefile.am
===================================================================
--- gnucash/trunk/src/gnome-utils/test/Makefile.am 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/gnome-utils/test/Makefile.am 2005-11-13 13:22:34 UTC (rev 11917)
@@ -45,6 +45,7 @@
test_gnc_recurrence_SOURCES=test-gnc-recurrence.c
test_gnc_recurrence_LDADD = ${GNOME_LIBS} \
+ ${top_builddir}/src/app-utils/libgncmod-app-utils.la \
${top_builddir}/src/gnome-utils/libgncmod-gnome-utils.la
test_gnc_dialog_LDADD = ${GNOME_LIBS} \
Modified: gnucash/trunk/src/import-export/qif-import/test/Makefile.am
===================================================================
--- gnucash/trunk/src/import-export/qif-import/test/Makefile.am 2005-11-12 15:23:57 UTC (rev 11916)
+++ gnucash/trunk/src/import-export/qif-import/test/Makefile.am 2005-11-13 13:22:34 UTC (rev 11917)
@@ -7,6 +7,7 @@
test_link_LDADD=../libgncmod-qif-import.la \
${top_builddir}/src/gnome/libgncgnome.la \
+ ${top_builddir}/src/gnome-utils/libgncmod-gnome-utils.la \
${top_builddir}/src/app-utils/libgncmod-app-utils.la \
${LIBXML2_LIBS}
More information about the gnucash-changes
mailing list