1 /********************************************************************\
2  * qofutil.c -- QOF utility functions                               *
3  * Copyright (C) 1997 Robin D. Clark                                *
4  * Copyright (C) 1997-2001,2004 Linas Vepstas <linas@linas.org>     *
5  * Copyright 2006,2008  Neil Williams  <linux@codehelp.co.uk>       *
6  *                                                                  *
7  * This program is free software; you can redistribute it and/or    *
8  * modify it under the terms of the GNU General Public License as   *
9  * published by the Free Software Foundation; either version 2 of   *
10  * the License, or (at your option) any later version.              *
11  *                                                                  *
12  * This program is distributed in the hope that it will be useful,  *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
15  * GNU General Public License for more details.                     *
16  *                                                                  *
17  * You should have received a copy of the GNU General Public License*
18  * along with this program; if not, contact:                        *
19  *                                                                  *
20  * Free Software Foundation           Voice:  +1-617-542-5942       *
21  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
22  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
23  *                                                                  *
24  *   Author: Rob Clark (rclark@cs.hmc.edu)                          *
25  *   Author: Linas Vepstas (linas@linas.org)                        *
26 \********************************************************************/
27 
28 #include "config.h"
29 
30 #include <errno.h>
31 #include <ctype.h>
32 #include <glib.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <math.h>
36 #include "qof.h"
37 #include "qofundo-p.h"
38 #include "qofbook-p.h"
39 
40 static QofLogModule log_module = QOF_MOD_UTIL;
41 
42 /* Search for str2 in first nchar chars of str1, ignore case..  Return
43  * pointer to first match, or null.  */
44 gchar *
strncasestr(const guchar * str1,const guchar * str2,size_t len)45 strncasestr (const guchar * str1, const guchar * str2, size_t len)
46 {
47 	while (*str1 && len--)
48 	{
49 		if (toupper (*str1) == toupper (*str2))
50 		{
51 			size_t l;
52 			l = strlen ((gchar*)str2);
53 			if (strncasecmp ((gchar*)str1, (gchar*)str2, l) == 0)
54 				return (gchar *) str1;
55 		}
56 		str1++;
57 	}
58 	return NULL;
59 }
60 
61 #ifndef HAVE_STRCASESTR
62 /* Search for str2 in str1, ignore case.  Return pointer to first
63  * match, or null.  */
64 gchar *
strcasestr(const gchar * str1,const gchar * str2)65 strcasestr (const gchar * str1, const gchar * str2)
66 {
67 	size_t len = strlen (str1);
68 	gchar *retval = strncasestr (str1, str2, len);
69 	return retval;
70 }
71 #endif
72 
73 /** \todo replace with g_strcmp0 from glib 2.16 */
74 gint
safe_strcmp(const gchar * da,const gchar * db)75 safe_strcmp (const gchar * da, const gchar * db)
76 {
77 	if ((da) && (db))
78 	{
79 		if ((da) != (db))
80 		{
81 			gint retval = strcmp ((da), (db));
82 			/* if strings differ, return */
83 			if (retval)
84 				return retval;
85 		}
86 	}
87 	else if ((!(da)) && (db))
88 		return -1;
89 	else if ((da) && (!(db)))
90 		return +1;
91 	return 0;
92 }
93 
94 gint
safe_strcasecmp(const gchar * da,const gchar * db)95 safe_strcasecmp (const gchar * da, const gchar * db)
96 {
97 	if ((da) && (db))
98 	{
99 		if ((da) != (db))
100 		{
101 			gint retval = strcasecmp ((da), (db));
102 			/* if strings differ, return */
103 			if (retval)
104 				return retval;
105 		}
106 	}
107 	else if ((!(da)) && (db))
108 		return -1;
109 	else if ((da) && (!(db)))
110 		return +1;
111 	return 0;
112 }
113 
114 inline gint
null_strcmp(const gchar * da,const gchar * db)115 null_strcmp (const gchar * da, const gchar * db)
116 {
117 	if (da && db)
118 		return strcmp (da, db);
119 	if (!da && db && 0 == db[0])
120 		return 0;
121 	if (!db && da && 0 == da[0])
122 		return 0;
123 	if (!da && db)
124 		return -1;
125 	if (da && !db)
126 		return +1;
127 	return 0;
128 }
129 
130 #define MAX_DIGITS 50
131 
132 /* inverse of strtoul */
133 gchar *
ultostr(gulong val,gint base)134 ultostr (gulong val, gint base)
135 {
136 	gchar buf[MAX_DIGITS];
137 	gulong broke[MAX_DIGITS];
138 	gint i;
139 	gulong places = 0, reval;
140 
141 	if ((2 > base) || (36 < base))
142 		return NULL;
143 
144 	/* count digits */
145 	places = 0;
146 	for (i = 0; i < MAX_DIGITS; i++)
147 	{
148 		broke[i] = val;
149 		places++;
150 		val /= base;
151 		if (0 == val)
152 			break;
153 	}
154 
155 	/* normalize */
156 	reval = 0;
157 	for (i = places - 2; i >= 0; i--)
158 	{
159 		reval += broke[i + 1];
160 		reval *= base;
161 		broke[i] -= reval;
162 	}
163 
164 	/* print */
165 	for (i = 0; i < (gint) places; i++)
166 	{
167 		if (10 > broke[i])
168 		{
169 			buf[places - 1 - i] = 0x30 + broke[i];	/* ascii digit zero */
170 		}
171 		else
172 		{
173 			buf[places - 1 - i] = 0x41 - 10 + broke[i];	/* ascii capital A */
174 		}
175 	}
176 	buf[places] = 0x0;
177 
178 	return g_strdup (buf);
179 }
180 
181 inline gint
qof_util_double_compare(gdouble d1,gdouble d2)182 qof_util_double_compare (gdouble d1, gdouble d2)
183 {
184 	if (isnan (d1) && isnan (d2))
185 		return 0;
186 	if (d1 < d2)
187 		return -1;
188 	if (d1 > d2)
189 		return 1;
190 	return 0;
191 }
192 
193 /* =================================================================== */
194 /* returns TRUE if the string is a number, possibly with whitespace */
195 /* =================================================================== */
196 
197 gboolean
qof_util_string_isnum(const guchar * s)198 qof_util_string_isnum (const guchar * s)
199 {
200 	if (s == NULL)
201 		return FALSE;
202 	if (*s == 0)
203 		return FALSE;
204 
205 	while (*s && isspace (*s))
206 		s++;
207 
208 	if (*s == 0)
209 		return FALSE;
210 	if (!isdigit (*s))
211 		return FALSE;
212 
213 	while (*s && isdigit (*s))
214 		s++;
215 
216 	if (*s == 0)
217 		return TRUE;
218 
219 	while (*s && isspace (*s))
220 		s++;
221 
222 	if (*s == 0)
223 		return TRUE;
224 
225 	return FALSE;
226 }
227 
228 /* =================================================================== */
229 /* Return NULL if the field is whitespace (blank, tab, formfeed etc.)
230  * Else return pointer to first non-whitespace character. */
231 /* =================================================================== */
232 
233 const gchar *
qof_util_whitespace_filter(const gchar * val)234 qof_util_whitespace_filter (const gchar * val)
235 {
236 	size_t len;
237 	if (!val)
238 		return NULL;
239 
240 	len = strspn (val, "\a\b\t\n\v\f\r ");
241 	if (0 == val[len])
242 		return NULL;
243 	return val + len;
244 }
245 
246 /* =================================================================== */
247 /* Return integer 1 if the string starts with 't' or 'T' or contains the
248  * word 'true' or 'TRUE'; if string is a number, return that number. */
249 /* =================================================================== */
250 
251 gint
qof_util_bool_to_int(const gchar * val)252 qof_util_bool_to_int (const gchar * val)
253 {
254 	const gchar *p = qof_util_whitespace_filter (val);
255 	if (!p)
256 		return 0;
257 	if ('t' == p[0])
258 		return 1;
259 	if ('T' == p[0])
260 		return 1;
261 	if ('y' == p[0])
262 		return 1;
263 	if ('Y' == p[0])
264 		return 1;
265 	if (strstr (p, "true"))
266 		return 1;
267 	if (strstr (p, "TRUE"))
268 		return 1;
269 	if (strstr (p, "yes"))
270 		return 1;
271 	if (strstr (p, "YES"))
272 		return 1;
273 	return atoi (val);
274 }
275 
276 /* =================================================================== */
277 /* Entity edit and commit utilities */
278 /* =================================================================== */
279 
280 gboolean
qof_util_param_edit(QofInstance * inst,const QofParam * param)281 qof_util_param_edit (QofInstance * inst, const QofParam *param)
282 {
283 	QofBackend *be;
284 	QofUndo *undo_data;
285 
286 	if (!inst)
287 		return FALSE;
288 	(inst->editlevel)++;
289 	if (1 < inst->editlevel)
290 		return FALSE;
291 	if (0 >= inst->editlevel)
292 		inst->editlevel = 1;
293 	be = qof_book_get_backend (inst->book);
294 	if (param != NULL)
295 	{
296 		undo_data = inst->book->undo_data;
297 		inst->param = param;
298 		if (undo_data->undo_operation_open)
299 			qof_undo_modify (inst, param);
300 	}
301 	if (be && qof_backend_begin_exists (be))
302 		qof_backend_run_begin (be, inst);
303 	else
304 		inst->dirty = TRUE;
305 	return TRUE;
306 }
307 
308 gboolean
qof_util_param_commit(QofInstance * inst,const QofParam * param)309 qof_util_param_commit (QofInstance * inst, const QofParam * param)
310 {
311 	QofUndo *undo_data;
312 	QofBackend * be;
313 
314 	if (!inst)
315 		return FALSE;
316 	(inst->editlevel)--;
317 	if (0 < inst->editlevel)
318 		return FALSE;
319 	be = qof_book_get_backend (inst->book);
320 	inst->param = param;
321 	if (be && qof_backend_commit_exists (be))
322 		qof_backend_run_commit (be, inst);
323 	if (param != NULL)
324 	{
325 		undo_data = inst->book->undo_data;
326 		if (undo_data->undo_operation_open)
327 			qof_undo_commit (inst, param);
328 	}
329 	return TRUE;
330 }
331 
332 gchar *
qof_util_make_utf8(gchar * string)333 qof_util_make_utf8 (gchar * string)
334 {
335 	gchar *value;
336 
337 	if (!string)
338 		return NULL;
339 	if (g_utf8_validate (string, -1, NULL))
340 		return string;
341 	value = g_locale_to_utf8 (string, -1, NULL, NULL, NULL);
342 	if (!value)
343 	{
344 		PWARN (" unable to convert from locale %s", string);
345 		PINFO ("trying to convert from ISO-8859-15.");
346 		value = g_convert (string, -1, "UTF-8", "ISO-8859-15",
347 			NULL, NULL, NULL);
348 		if (!value)
349 		{
350 			PERR (" conversion failed");
351 			return string;
352 		}
353 		return value;
354 	}
355 	return value;
356 }
357 
358 /* =================================================================== */
359 /* The QOF string cache - reimplements a limited GCache for strings    */
360 /* =================================================================== */
361 
362 typedef struct {
363 	GHashTable *key_table;
364 	GHashTable *value_table;
365 }QStrCache;
366 
367 static QStrCache *qof_string_cache = NULL;
368 
369 typedef struct {
370 	gpointer value;
371 	gint ref_count;
372 } QStrCacheNode;
373 
g_cache_node_new(gpointer value)374 static inline QStrCacheNode* g_cache_node_new (gpointer value) {
375 	QStrCacheNode *node = g_slice_new (QStrCacheNode);
376 	node->value = value;
377 	node->ref_count = 1;
378 	return node;
379 }
380 
g_cache_node_destroy(QStrCacheNode * node)381 static inline void g_cache_node_destroy (QStrCacheNode *node) {
382 	g_slice_free (QStrCacheNode, node);
383 }
384 
qof_cache_new(void)385 static QStrCache* qof_cache_new (void) {
386 	QStrCache *cache;
387 	cache = g_slice_new (QStrCache);
388 	cache->key_table = g_hash_table_new (g_str_hash, g_str_equal);
389 	cache->value_table = g_hash_table_new (g_str_hash, NULL);
390 	return cache;
391 }
392 
qof_cache_destroy(QStrCache * cache)393 static void qof_cache_destroy (QStrCache *cache) {
394 	g_return_if_fail (cache != NULL);
395 	g_hash_table_destroy (cache->key_table);
396 	g_hash_table_destroy (cache->value_table);
397 	g_slice_free (QStrCache, cache);
398 }
399 
qof_cache_insert(QStrCache * cache,gpointer key)400 static gpointer qof_cache_insert (QStrCache *cache, gpointer key) {
401 	QStrCacheNode *node;
402 	gpointer value;
403 
404 	g_return_val_if_fail (cache != NULL, NULL);
405 	node = g_hash_table_lookup (cache->key_table, key);
406 	if (node) {
407 		node->ref_count += 1;
408 		return node->value;
409 	}
410 	key = g_strdup (key);
411 	value = g_strdup (key);
412 	node = g_cache_node_new (value);
413 	g_hash_table_insert (cache->key_table, key, node);
414 	g_hash_table_insert (cache->value_table, value, key);
415 	return node->value;
416 }
417 
qof_cache_remove(QStrCache * cache,gconstpointer value)418 static void qof_cache_remove (QStrCache *cache, gconstpointer value) {
419 	QStrCacheNode *node;
420 	gpointer key;
421 
422 	g_return_if_fail (cache != NULL);
423 	key = g_hash_table_lookup (cache->value_table, value);
424 	node = g_hash_table_lookup (cache->key_table, key);
425 	g_return_if_fail (node != NULL);
426 	node->ref_count -= 1;
427 	if (node->ref_count == 0) {
428 		g_hash_table_remove (cache->value_table, value);
429 		g_hash_table_remove (cache->key_table, key);
430 		g_free (key);
431 		g_free (node->value);
432 		g_cache_node_destroy (node);
433 	}
434 }
435 
qof_util_get_string_cache(void)436 static QStrCache * qof_util_get_string_cache (void) {
437 	if (!qof_string_cache) {
438 		qof_string_cache = qof_cache_new ();
439 	}
440 	return qof_string_cache;
441 }
442 
qof_util_string_cache_destroy(void)443 void qof_util_string_cache_destroy (void) {
444 	if (qof_string_cache) {
445 		qof_cache_destroy (qof_string_cache);
446 	}
447 	qof_string_cache = NULL;
448 }
449 
qof_util_string_cache_remove(gconstpointer key)450 void qof_util_string_cache_remove (gconstpointer key) {
451 	if (key) {
452 		qof_cache_remove (qof_util_get_string_cache (), key);
453 	}
454 }
455 
qof_util_string_cache_insert(gconstpointer key)456 gpointer qof_util_string_cache_insert (gconstpointer key) {
457 	if (key) {
458 		return qof_cache_insert(qof_util_get_string_cache(), (gpointer)key);
459 	}
460 	return NULL;
461 }
462 
463 gchar *
qof_util_param_to_string(QofEntity * ent,const QofParam * param)464 qof_util_param_to_string (QofEntity * ent, const QofParam * param)
465 {
466 	gchar *param_string;
467 	gchar param_sa[GUID_ENCODING_LENGTH + 1];
468 	gboolean known_type;
469 	QofType paramType;
470 	const GUID *param_guid;
471 	QofNumeric param_numeric, (*numeric_getter) (QofEntity *, const QofParam *);
472 	gdouble param_double, (*double_getter) (QofEntity *, const QofParam *);
473 	gboolean param_boolean, (*boolean_getter) (QofEntity *, const QofParam *);
474 	gint32 param_i32, (*int32_getter) (QofEntity *, const QofParam *);
475 	gint64 param_i64, (*int64_getter) (QofEntity *, const QofParam *);
476 	gchar param_char, (*char_getter) (QofEntity *, const QofParam *);
477 
478 	param_string = NULL;
479 	known_type = FALSE;
480 	g_return_val_if_fail (ent && param, NULL);
481 	paramType = param->param_type;
482 	if (safe_strcmp (paramType, QOF_TYPE_STRING) == 0)
483 	{
484 		param_string = g_strdup (param->param_getfcn (ent, param));
485 		if (param_string == NULL)
486 			param_string = g_strdup("");
487 		known_type = TRUE;
488 		return param_string;
489 	}
490 	if (safe_strcmp (paramType, QOF_TYPE_TIME) == 0)
491 	{
492 		QofTime *param_qt;
493 		QofDate *qd;
494 		param_qt = param->param_getfcn (ent, param);
495 		qd = qof_date_from_qtime (param_qt);
496 		return qof_date_print (qd, QOF_DATE_FORMAT_UTC);
497 	}
498 	if ((safe_strcmp (paramType, QOF_TYPE_NUMERIC) == 0) ||
499 		(safe_strcmp (paramType, QOF_TYPE_DEBCRED) == 0))
500 	{
501 		numeric_getter =
502 			(QofNumeric (*)(QofEntity *, const QofParam *)) param->param_getfcn;
503 		param_numeric = numeric_getter (ent, param);
504 		param_string = g_strdup (qof_numeric_to_string (param_numeric));
505 		known_type = TRUE;
506 		return param_string;
507 	}
508 	if (safe_strcmp (paramType, QOF_TYPE_GUID) == 0)
509 	{
510 		param_guid = param->param_getfcn (ent, param);
511 		guid_to_string_buff (param_guid, param_sa);
512 		param_string = g_strdup (param_sa);
513 		known_type = TRUE;
514 		return param_string;
515 	}
516 	if (safe_strcmp (paramType, QOF_TYPE_INT32) == 0)
517 	{
518 		int32_getter =
519 			(gint32 (*)(QofEntity *, const QofParam *)) param->param_getfcn;
520 		param_i32 = int32_getter (ent, param);
521 		param_string = g_strdup_printf ("%d", param_i32);
522 		known_type = TRUE;
523 		return param_string;
524 	}
525 	if (safe_strcmp (paramType, QOF_TYPE_INT64) == 0)
526 	{
527 		int64_getter =
528 			(gint64 (*)(QofEntity *, const QofParam *)) param->param_getfcn;
529 		param_i64 = int64_getter (ent, param);
530 		param_string = g_strdup_printf ("%" G_GINT64_FORMAT, param_i64);
531 		known_type = TRUE;
532 		return param_string;
533 	}
534 	if (safe_strcmp (paramType, QOF_TYPE_DOUBLE) == 0)
535 	{
536 		double_getter =
537 			(double (*)(QofEntity *, const QofParam *)) param->param_getfcn;
538 		param_double = double_getter (ent, param);
539 		param_string = g_strdup_printf ("%f", param_double);
540 		known_type = TRUE;
541 		return param_string;
542 	}
543 	if (safe_strcmp (paramType, QOF_TYPE_BOOLEAN) == 0)
544 	{
545 		boolean_getter =
546 			(gboolean (*)(QofEntity *, const QofParam *)) param->param_getfcn;
547 		param_boolean = boolean_getter (ent, param);
548 		/* Boolean values need to be lowercase for QSF validation. */
549 		if (param_boolean == TRUE)
550 		{
551 			param_string = g_strdup ("true");
552 		}
553 		else
554 		{
555 			param_string = g_strdup ("false");
556 		}
557 		known_type = TRUE;
558 		return param_string;
559 	}
560 	/* "kvp" contains repeating values, cannot be a single string for the frame. */
561 	if (safe_strcmp (paramType, QOF_TYPE_KVP) == 0)
562 	{
563 		KvpFrame *frame = NULL;
564 		frame = param->param_getfcn (ent, param);
565 		known_type = TRUE;
566 		if (!kvp_frame_is_empty (frame))
567 		{
568 			GHashTable *hash = kvp_frame_get_hash (frame);
569 			param_string = g_strdup_printf ("%s(%d)", QOF_TYPE_KVP,
570 				g_hash_table_size (hash));
571 		}
572 		/* ensure a newly allocated string is returned, even
573 		if the frame is empty. */
574 		else
575 		{
576 			param_string = g_strdup("");
577 		}
578 		return param_string;
579 	}
580 	if (safe_strcmp (paramType, QOF_TYPE_CHAR) == 0)
581 	{
582 		char_getter =
583 			(gchar (*)(QofEntity *, const QofParam *)) param->param_getfcn;
584 		param_char = char_getter (ent, param);
585 		known_type = TRUE;
586 		return g_strdup_printf ("%c", param_char);
587 	}
588 	/* "collect" contains repeating values, cannot be a single string. */
589 	if (safe_strcmp (paramType, QOF_TYPE_COLLECT) == 0)
590 	{
591 		QofCollection *col = NULL;
592 		col = param->param_getfcn (ent, param);
593 		known_type = TRUE;
594 		return g_strdup_printf ("%s(%d)",
595 			qof_collection_get_type (col), qof_collection_count (col));
596 	}
597 	if (safe_strcmp (paramType, QOF_TYPE_CHOICE) == 0)
598 	{
599 		QofEntity *child = NULL;
600 		child = param->param_getfcn (ent, param);
601 		if (!child)
602 		{
603 			return param_string;
604 		}
605 		known_type = TRUE;
606 		return g_strdup (qof_object_printable (child->e_type, child));
607 	}
608 	if (safe_strcmp (paramType, QOF_PARAM_BOOK) == 0)
609 	{
610 		QofBackend *be;
611 		QofBook *book;
612 		book = param->param_getfcn (ent, param);
613 		PINFO (" book param %p", book);
614 		be = qof_book_get_backend (book);
615 		known_type = TRUE;
616 		PINFO (" backend=%p", be);
617 		if (!be)
618 		{
619 			return QOF_PARAM_BOOK;
620 		}
621 		param_string = g_strdup (be->fullpath);
622 		PINFO (" fullpath=%s", param_string);
623 		if (param_string)
624 		{
625 			return param_string;
626 		}
627 		param_guid = qof_entity_get_guid ((QofEntity*)book);
628 		guid_to_string_buff (param_guid, param_sa);
629 		PINFO (" book GUID=%s", param_sa);
630 		param_string = g_strdup (param_sa);
631 		return param_string;
632 	}
633 	if (!known_type)
634 	{
635 		QofEntity *child = NULL;
636 		child = param->param_getfcn (ent, param);
637 		if (!child)
638 		{
639 			return param_string;
640 		}
641 		return g_strdup (qof_object_printable (child->e_type, child));
642 	}
643 	return g_strdup ("");
644 }
645 
646 gboolean
qof_util_param_set_string(QofEntity * ent,const QofParam * param,const gchar * value_string)647 qof_util_param_set_string (QofEntity * ent, const QofParam * param,
648 	const gchar * value_string)
649 {
650 	void (*string_setter) (QofEntity *, const gchar *);
651 	void (*time_setter) (QofEntity *, QofTime *);
652 	void (*numeric_setter) (QofEntity *, QofNumeric);
653 	void (*guid_setter) (QofEntity *, const GUID *);
654 	void (*double_setter) (QofEntity *, gdouble);
655 	void (*boolean_setter) (QofEntity *, gboolean);
656 	void (*i32_setter) (QofEntity *, gint32);
657 	void (*i64_setter) (QofEntity *, gint64);
658 	void (*char_setter) (QofEntity *, gchar);
659 /*	void (*kvp_frame_setter) (QofEntity *, KvpFrame *);
660 	void (*reference_setter) (QofEntity *, QofEntity *);
661 	void (*collection_setter) (QofEntity *, QofCollection *);*/
662 
663 	g_return_val_if_fail (ent, FALSE);
664 	g_return_val_if_fail (param, FALSE);
665 	g_return_val_if_fail (value_string, FALSE);
666 
667 	if (safe_strcmp (param->param_type, QOF_TYPE_STRING) == 0)
668 	{
669 		string_setter =
670 			(void (*)(QofEntity *,
671 				const gchar *)) param->param_setfcn;
672 		if (string_setter != NULL)
673 			string_setter (ent, value_string);
674 //		registered_type = TRUE;
675 	}
676 	if (safe_strcmp (param->param_type, QOF_TYPE_TIME) == 0)
677 	{
678 		QofTime *qt;
679 		QofDate *qd;
680 
681 		qd = qof_date_parse (value_string, QOF_DATE_FORMAT_UTC);
682 		if (!qd)
683 			return FALSE;
684 		qt = qof_date_to_qtime (qd);
685 		time_setter =
686 			(void (*)(QofEntity *, QofTime *))
687 			param->param_setfcn;
688 		if ((time_setter != NULL) && (qof_time_is_valid (qt)))
689 			time_setter (ent, qt);
690 		qof_date_free (qd);
691 //		registered_type = TRUE;
692 	}
693 	if ((safe_strcmp (param->param_type, QOF_TYPE_NUMERIC) == 0) ||
694 		(safe_strcmp (param->param_type, QOF_TYPE_DEBCRED) == 0))
695 	{
696 		QofNumeric num;
697 		numeric_setter =
698 			(void (*)(QofEntity *,
699 				QofNumeric)) param->param_setfcn;
700 		if (!qof_numeric_from_string (value_string, &num) ||
701 			(qof_numeric_check (num) != QOF_ERROR_OK))
702 			return FALSE;
703 		if (numeric_setter != NULL)
704 			numeric_setter (ent, num);
705 //		registered_type = TRUE;
706 	}
707 	if (safe_strcmp (param->param_type, QOF_TYPE_GUID) == 0)
708 	{
709 		GUID * guid;
710 
711 		guid = guid_malloc();
712 		guid_new (guid);
713 		guid_setter =
714 			(void (*)(QofEntity *,
715 				const GUID *)) param->param_setfcn;
716 		if (!string_to_guid(value_string, guid))
717 			return FALSE;
718 		if (guid_setter != NULL)
719 			guid_setter (ent, guid);
720 //		registered_type = TRUE;
721 	}
722 	if (safe_strcmp (param->param_type, QOF_TYPE_INT32) == 0)
723 	{
724 		gint32 i32;
725 		gchar *tail;
726 
727 		errno = 0;
728 		i32_setter =
729 			(void (*)(QofEntity *, gint32)) param->param_setfcn;
730 		i32 =
731 			(gint32) strtol (value_string, &tail, 0);
732 		if ((i32_setter != NULL) && (errno == 0))
733 
734 			i32_setter (ent, i32);
735 //		registered_type = TRUE;
736 	}
737 	if (safe_strcmp (param->param_type, QOF_TYPE_INT64) == 0)
738 	{
739 		gint64 i64;
740 		gchar *tail;
741 
742 		errno = 0;
743 		i64 = strtoll (value_string, &tail, 0);
744 		i64_setter =
745 			(void (*)(QofEntity *, gint64)) param->param_setfcn;
746 		if ((i64_setter != NULL) && (errno == 0))
747 			i64_setter (ent, i64);
748 //		registered_type = TRUE;
749 	}
750 	if (safe_strcmp (param->param_type, QOF_TYPE_DOUBLE) == 0)
751 	{
752 		gdouble db;
753 		gchar *tail;
754 
755 		errno = 0;
756 		db = strtod (value_string, &tail);
757 		double_setter =
758 			(void (*)(QofEntity *, gdouble)) param->param_setfcn;
759 		if ((double_setter != NULL) && (errno == 0))
760 			double_setter (ent, db);
761 //		registered_type = TRUE;
762 	}
763 	if (safe_strcmp (param->param_type, QOF_TYPE_BOOLEAN) == 0)
764 	{
765 		gint val;
766 		gboolean G_GNUC_UNUSED b;
767 
768 		boolean_setter =
769 			(void (*)(QofEntity *, gboolean)) param->param_setfcn;
770 		val = qof_util_bool_to_int(value_string);
771 		if ((val > 1) || (val < 0))
772 			return FALSE;
773 		b = (val == 1) ? TRUE : FALSE;
774 		if (boolean_setter != NULL)
775 			boolean_setter (ent, val);
776 //		registered_type = TRUE;
777 	}
778 	if (safe_strcmp (param->param_type, QOF_TYPE_KVP) == 0)
779 	{
780 		/* unsupported */
781 		return FALSE;
782 /*		KvpFrame * frame;
783 		KvpValue * value;
784 
785 		kvp_frame_setter =
786 			(void (*)(QofEntity *, KvpFrame *)) param->param_setfcn;
787 		if (kvp_frame_setter != NULL)
788 			kvp_frame_setter (rule->targetEnt, cm_kvp);
789 //		registered_type = TRUE;*/
790 	}
791 	if (safe_strcmp (param->param_type, QOF_TYPE_CHAR) == 0)
792 	{
793 		char_setter =
794 			(void (*)(QofEntity *, gchar)) param->param_setfcn;
795 		if (char_setter != NULL)
796 			char_setter (ent, value_string[0]);
797 //		registered_type = TRUE;
798 	}
799 	if (safe_strcmp (param->param_type, QOF_TYPE_COLLECT) == 0)
800 	{
801 		/* unsupported */
802 		return FALSE;
803 	}
804 	if (safe_strcmp (param->param_type, QOF_TYPE_CHOICE) == 0)
805 	{
806 		/* unsupported*/
807 		return FALSE;
808 	}
809 /*	if (registered_type == FALSE)
810 	{
811 		referenceEnt =
812 			cm_param->param_getfcn (rule->importEnt, cm_param);
813 		if (referenceEnt)
814 		{
815 			reference_setter =
816 				(void (*)(QofEntity *, QofEntity *)) cm_param->
817 				param_setfcn;
818 			if (reference_setter != NULL)
819 			{
820 				reference_setter (rule->targetEnt, referenceEnt);
821 			}
822 		}
823 	}*/
824 	return TRUE;
825 }
826 
827 
828 void
qof_init(void)829 qof_init (void)
830 {
831 	qof_util_get_string_cache ();
832 	guid_init ();
833 	qof_date_init ();
834 	qof_object_initialize ();
835 	qof_query_init ();
836 	qof_book_register ();
837 }
838 
839 void
qof_close(void)840 qof_close (void)
841 {
842 	qof_query_shutdown ();
843 	qof_object_shutdown ();
844 	guid_shutdown ();
845 	qof_date_close ();
846 	qof_util_string_cache_destroy ();
847 }
848 
849 /* ************************ END OF FILE ***************************** */
850