Convert kvp-scm to C++ and to using the KVP C++ API.

The binding remains C to simplify interaction of these two functions with
SWIG and Scheme.
This commit is contained in:
John Ralls
2015-06-22 15:00:10 -07:00
parent 78b5b7cb5b
commit 9e142124f4
5 changed files with 41 additions and 313 deletions

View File

@@ -184,7 +184,7 @@ src/engine/gnc-pricedb.c
src/engine/gnc-session.c
src/engine/gncTaxTable.c
src/engine/gncVendor.c
src/engine/kvp-scm.c
src/engine/kvp-scm.cpp
src/engine/policy.c
src/engine/Query.c
src/engine/Recurrence.c

View File

@@ -38,7 +38,7 @@ libgncmod_engine_la_SOURCES = \
gnc-session.c \
gncmod-engine.c \
swig-engine.c \
kvp-scm.c \
kvp-scm.cpp \
engine-helpers.c \
glib-helpers.c \
policy.c \

View File

@@ -38,7 +38,6 @@
#include "guile-mappings.h"
#include "gnc-guile-utils.h"
#include <qof.h>
#include <kvp_frame.h>
#include <qofbookslots.h>
/** \todo Code dependent on the private query headers
@@ -668,287 +667,6 @@ gnc_query_path_free (GSList *path)
g_slist_free (path);
}
static KvpValueType
gnc_scm2KvpValueType (SCM value_type_scm)
{
return scm_to_int(value_type_scm);
}
static SCM gnc_kvp_frame2scm (KvpFrame *frame);
static SCM
gnc_kvp_value2scm (const KvpValue *value)
{
SCM value_scm = SCM_EOL;
KvpValueType value_t;
SCM scm;
const gchar *string;
if (!value) return SCM_BOOL_F;
value_t = kvp_value_get_type (value);
value_scm = scm_cons (scm_from_long (value_t), value_scm);
switch (value_t)
{
case KVP_TYPE_GINT64:
scm = scm_from_int64 (kvp_value_get_gint64 (value));
break;
case KVP_TYPE_DOUBLE:
scm = scm_from_double (kvp_value_get_double (value));
break;
case KVP_TYPE_STRING:
string = kvp_value_get_string (value);
scm = string ? scm_from_utf8_string (string) : SCM_BOOL_F;
break;
case KVP_TYPE_GUID:
scm = gnc_guid2scm (*kvp_value_get_guid (value));
break;
case KVP_TYPE_TIMESPEC:
scm = gnc_timespec2timepair (kvp_value_get_timespec (value));
break;
case KVP_TYPE_NUMERIC:
{
gnc_numeric n = kvp_value_get_numeric (value);
scm = gnc_query_numeric2scm (n);
break;
}
case KVP_TYPE_GLIST:
{
GList *node;
scm = SCM_EOL;
for (node = kvp_value_get_glist (value); node; node = node->next)
scm = scm_cons (gnc_kvp_value2scm (node->data), scm);
scm = scm_reverse (scm);
break;
}
case KVP_TYPE_FRAME:
scm = gnc_kvp_frame2scm (kvp_value_get_frame (value));
break;
default:
scm = SCM_BOOL_F;
break;
}
value_scm = scm_cons (scm, value_scm);
return scm_reverse (value_scm);
}
typedef struct
{
SCM scm;
} KVPSCMData;
static void
kvp_frame_slot2scm (const char *key, KvpValue *value, gpointer data)
{
KVPSCMData *ksd = data;
SCM value_scm;
SCM key_scm;
SCM pair;
key_scm = key ? scm_from_utf8_string (key) : SCM_BOOL_F;
value_scm = gnc_kvp_value2scm (value);
pair = scm_cons (key_scm, value_scm);
ksd->scm = scm_cons (pair, ksd->scm);
}
static SCM
gnc_kvp_frame2scm (KvpFrame *frame)
{
KVPSCMData ksd;
if (!frame) return SCM_BOOL_F;
ksd.scm = SCM_EOL;
kvp_frame_for_each_slot (frame, kvp_frame_slot2scm, &ksd);
return ksd.scm;
}
static KvpFrame * gnc_scm2KvpFrame (SCM frame_scm);
static KvpValue *
gnc_scm2KvpValue (SCM value_scm)
{
KvpValueType value_t;
KvpValue *value = NULL;
SCM type_scm;
SCM val_scm;
if (!scm_is_list (value_scm) || scm_is_null (value_scm))
return NULL;
type_scm = SCM_CAR (value_scm);
value_t = gnc_scm2KvpValueType (type_scm);
value_scm = SCM_CDR (value_scm);
if (!scm_is_list (value_scm) || scm_is_null (value_scm))
return NULL;
val_scm = SCM_CAR (value_scm);
switch (value_t)
{
case KVP_TYPE_GINT64:
value = kvp_value_new_gint64 (scm_to_int64 (val_scm));
break;
case KVP_TYPE_DOUBLE:
value = kvp_value_new_double (scm_to_double (val_scm));
break;
case KVP_TYPE_STRING:
{
gchar * str;
str = gnc_scm_to_utf8_string (val_scm);
value = kvp_value_new_string (str);
g_free (str);
break;
}
case KVP_TYPE_GUID:
{
if (val_scm != SCM_BOOL_F)
{
GncGUID guid = gnc_scm2guid (val_scm);
value = kvp_value_new_guid (&guid);
}
else
value = NULL;
break;
}
case KVP_TYPE_TIMESPEC:
{
Timespec ts = gnc_timepair2timespec (val_scm);
value = kvp_value_new_timespec(ts);
break;
}
case KVP_TYPE_GDATE:
{
Timespec ts = gnc_timepair2timespec (val_scm);
value = kvp_value_new_gdate(timespec_to_gdate(ts));
break;
}
case KVP_TYPE_NUMERIC:
{
gnc_numeric n;
if (!gnc_query_numeric_p (val_scm))
return NULL;
n = gnc_query_scm2numeric (val_scm);
value = kvp_value_new_gnc_numeric (n);
break;
}
case KVP_TYPE_GLIST:
{
GList *list = NULL;
GList *node;
for (; scm_is_list (val_scm) && !scm_is_null (val_scm);
val_scm = SCM_CDR (val_scm))
{
SCM scm = SCM_CAR (val_scm);
list = g_list_prepend (list, gnc_scm2KvpValue (scm));
}
list = g_list_reverse (list);
value = kvp_value_new_glist (list);
for (node = list; node; node = node->next)
kvp_value_delete (node->data);
g_list_free (list);
break;
}
case KVP_TYPE_FRAME:
{
KvpFrame *frame;
frame = gnc_scm2KvpFrame (val_scm);
value = kvp_value_new_frame (frame);
kvp_frame_delete (frame);
break;
}
default:
break;
}
return value;
}
static KvpFrame *
gnc_scm2KvpFrame (SCM frame_scm)
{
KvpFrame * frame;
if (!scm_is_list (frame_scm)) return NULL;
frame = kvp_frame_new ();
for (; scm_is_list (frame_scm) && !scm_is_null (frame_scm);
frame_scm = SCM_CDR (frame_scm))
{
SCM pair = SCM_CAR (frame_scm);
KvpValue *value;
SCM key_scm;
SCM val_scm;
gchar *key;
if (!scm_is_pair (pair))
continue;
key_scm = SCM_CAR (pair);
val_scm = SCM_CDR (pair);
if (!scm_is_string (key_scm))
continue;
key = scm_to_utf8_string (key_scm); /* key should be freed with free !
This is automatically taken care
of by scm_dynwind_free below. */
scm_dynwind_begin (0);
scm_dynwind_free (key); /* free key whenever the dynwind context ends */
if (!key)
{
scm_dynwind_end ();
continue;
}
value = gnc_scm2KvpValue (val_scm); /* can exit non-locally so justifies
the use of scm_dynwind context
protection */
if (!value)
{
scm_dynwind_end ();
continue;
}
kvp_frame_set_slot_nc (frame, key, value);
scm_dynwind_end ();
}
return frame;
}
static SCM
gnc_queryterm2scm (const QofQueryTerm *qt)

View File

@@ -1,14 +1,19 @@
#include <libguile.h>
extern "C"
{
#include "config.h"
#include <qof.h>
#include <kvp_frame.h>
#include <libguile.h>
#include "engine-helpers-guile.h"
#include "kvp-scm.h"
#include "guile-mappings.h"
#include "gnc-guile-utils.h"
#include "swig-runtime.h"
#include "kvp-scm.h"
}
#include <kvp_frame.hpp>
/* NOTE: There are some problems with this approach. Currently,
* guids are stored simply as strings in scheme, so some
@@ -25,43 +30,40 @@ gnc_scm_to_kvp_value_ptr(SCM val)
/* in guile 1.8 (exact? ) only works on numbers */
if (scm_is_exact (val) && gnc_gh_gint64_p(val))
{
return kvp_value_new_gint64(scm_to_int64(val));
return new KvpValue{scm_to_int64(val)};
}
else
{
return kvp_value_new_double(scm_to_double(val));
return new KvpValue{scm_to_double(val)};
}
}
else if (gnc_numeric_p(val))
{
return kvp_value_new_gnc_numeric(gnc_scm_to_numeric(val));
return new KvpValue{gnc_scm_to_numeric(val)};
}
else if (gnc_guid_p(val))
{
GncGUID tmpguid = gnc_scm2guid(val);
return kvp_value_new_guid(&tmpguid);
auto guid = gnc_scm2guid(val);
auto tmpguid = guid_copy(&guid);
return new KvpValue{tmpguid};
}
else if (gnc_timepair_p(val))
{
Timespec ts = gnc_timepair2timespec(val);
return kvp_value_new_timespec(ts);
return new KvpValue{ts};
}
else if (scm_is_string(val))
{
gchar *newstr;
KvpValue *ret;
newstr = gnc_scm_to_utf8_string (val);
ret = kvp_value_new_string(newstr);
g_free (newstr);
return ret;
return new KvpValue{gnc_scm_to_utf8_string(val)};
}
else if (SWIG_IsPointerOfType(val, SWIG_TypeQuery("_p_KvpFrame")))
{
#define FUNC_NAME G_STRFUNC
KvpFrame *frame = SWIG_MustGetPtr(val, SWIG_TypeQuery("_p_KvpFrame"),
1, 0);
auto vp_frame = SWIG_MustGetPtr(val,
SWIG_TypeQuery("_p_KvpFrame"), 1, 0);
KvpFrame *frame = static_cast<KvpFrame*>(vp_frame);
#undef FUNC_NAME
return kvp_value_new_frame (frame);
return new KvpValue{frame};
}
/* FIXME: add list handler here */
return NULL;
@@ -70,41 +72,42 @@ gnc_scm_to_kvp_value_ptr(SCM val)
SCM
gnc_kvp_value_ptr_to_scm(KvpValue* val)
{
const gchar *string;
switch (kvp_value_get_type(val))
{
case KVP_TYPE_GINT64:
return scm_from_int64(kvp_value_get_gint64(val));
return scm_from_int64(val->get<int64_t>());
break;
case KVP_TYPE_DOUBLE:
return scm_from_double (kvp_value_get_double(val));
return scm_from_double (val->get<double>());
break;
case KVP_TYPE_NUMERIC:
return gnc_numeric_to_scm(kvp_value_get_numeric(val));
return gnc_numeric_to_scm(val->get<gnc_numeric>());
break;
case KVP_TYPE_STRING:
string = kvp_value_get_string(val);
{
auto string = val->get<const char*>();
return string ? scm_from_utf8_string(string) : SCM_BOOL_F;
break;
}
case KVP_TYPE_GUID:
{
GncGUID *tempguid = kvp_value_get_guid(val);
auto tempguid = kvp_value_get_guid(val);
return gnc_guid2scm(*tempguid);
}
break;
case KVP_TYPE_TIMESPEC:
return gnc_timespec2timepair(kvp_value_get_timespec(val));
return gnc_timespec2timepair(val->get<Timespec>());
break;
case KVP_TYPE_FRAME:
{
KvpFrame *frame = kvp_value_get_frame(val);
if (frame)
auto frame = val->get<KvpFrame*>();
if (frame != nullptr)
return SWIG_NewPointerObj(frame, SWIG_TypeQuery("_p_KvpFrame"), 0);
}
break;
case KVP_TYPE_GDATE:
return gnc_timespec2timepair(gdate_to_timespec(kvp_value_get_gdate(val)));
return gnc_timespec2timepair(gdate_to_timespec(val->get<GDate>()));
/* FIXME: handle types below */
case KVP_TYPE_GLIST:

View File

@@ -1,11 +1,18 @@
#ifndef KVP_SCM_H
#define KVP_SCM_H
#include "qof.h"
#ifdef __cplusplus
extern "C"
{
#endif
#include <qof.h>
#include <libguile.h>
KvpValue* gnc_scm_to_kvp_value_ptr(SCM kvpval);
SCM gnc_kvp_value_ptr_to_scm(KvpValue* val);
#ifdef __cplusplus
}
#endif
#endif /* KVP_SCM_H */