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