00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "config.h"
00029
00030 #include <errno.h>
00031 #include <ctype.h>
00032 #include <glib.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <math.h>
00036 #include "qof.h"
00037 #include "qofundo-p.h"
00038 #include "qofbook-p.h"
00039
00040 static QofLogModule log_module = QOF_MOD_UTIL;
00041
00042
00043
00044 gchar *
00045 strncasestr (const guchar * str1, const guchar * str2, size_t len)
00046 {
00047 while (*str1 && len--)
00048 {
00049 if (toupper (*str1) == toupper (*str2))
00050 {
00051 if (strncasecmp (str1, str2, strlen (str2)) == 0)
00052 return (gchar *) str1;
00053 }
00054 str1++;
00055 }
00056 return NULL;
00057 }
00058
00059 #ifndef HAVE_STRCASESTR
00060
00061
00062 gchar *
00063 strcasestr (const gchar * str1, const gchar * str2)
00064 {
00065 size_t len = strlen (str1);
00066 gchar *retval = strncasestr (str1, str2, len);
00067 return retval;
00068 }
00069 #endif
00070
00071 gint
00072 safe_strcmp (const gchar * da, const gchar * db)
00073 {
00074 if ((da) && (db))
00075 {
00076 if ((da) != (db))
00077 {
00078 gint retval = strcmp ((da), (db));
00079
00080 if (retval)
00081 return retval;
00082 }
00083 }
00084 else if ((!(da)) && (db))
00085 return -1;
00086 else if ((da) && (!(db)))
00087 return +1;
00088 return 0;
00089 }
00090
00091 gint
00092 safe_strcasecmp (const gchar * da, const gchar * db)
00093 {
00094 if ((da) && (db))
00095 {
00096 if ((da) != (db))
00097 {
00098 gint retval = strcasecmp ((da), (db));
00099
00100 if (retval)
00101 return retval;
00102 }
00103 }
00104 else if ((!(da)) && (db))
00105 return -1;
00106 else if ((da) && (!(db)))
00107 return +1;
00108 return 0;
00109 }
00110
00111 inline gint
00112 null_strcmp (const gchar * da, const gchar * db)
00113 {
00114 if (da && db)
00115 return strcmp (da, db);
00116 if (!da && db && 0 == db[0])
00117 return 0;
00118 if (!db && da && 0 == da[0])
00119 return 0;
00120 if (!da && db)
00121 return -1;
00122 if (da && !db)
00123 return +1;
00124 return 0;
00125 }
00126
00127 #define MAX_DIGITS 50
00128
00129
00130 gchar *
00131 ultostr (gulong val, gint base)
00132 {
00133 gchar buf[MAX_DIGITS];
00134 gulong broke[MAX_DIGITS];
00135 gint i;
00136 gulong places = 0, reval;
00137
00138 if ((2 > base) || (36 < base))
00139 return NULL;
00140
00141
00142 places = 0;
00143 for (i = 0; i < MAX_DIGITS; i++)
00144 {
00145 broke[i] = val;
00146 places++;
00147 val /= base;
00148 if (0 == val)
00149 break;
00150 }
00151
00152
00153 reval = 0;
00154 for (i = places - 2; i >= 0; i--)
00155 {
00156 reval += broke[i + 1];
00157 reval *= base;
00158 broke[i] -= reval;
00159 }
00160
00161
00162 for (i = 0; i < (gint) places; i++)
00163 {
00164 if (10 > broke[i])
00165 {
00166 buf[places - 1 - i] = 0x30 + broke[i];
00167 }
00168 else
00169 {
00170 buf[places - 1 - i] = 0x41 - 10 + broke[i];
00171 }
00172 }
00173 buf[places] = 0x0;
00174
00175 return g_strdup (buf);
00176 }
00177
00178 inline gint
00179 qof_util_double_compare (gdouble d1, gdouble d2)
00180 {
00181 if (isnan (d1) && isnan (d2))
00182 return 0;
00183 if (d1 < d2)
00184 return -1;
00185 if (d1 > d2)
00186 return 1;
00187 return 0;
00188 }
00189
00190
00191
00192
00193
00194 gboolean
00195 qof_util_string_isnum (const guchar * s)
00196 {
00197 if (s == NULL)
00198 return FALSE;
00199 if (*s == 0)
00200 return FALSE;
00201
00202 while (*s && isspace (*s))
00203 s++;
00204
00205 if (*s == 0)
00206 return FALSE;
00207 if (!isdigit (*s))
00208 return FALSE;
00209
00210 while (*s && isdigit (*s))
00211 s++;
00212
00213 if (*s == 0)
00214 return TRUE;
00215
00216 while (*s && isspace (*s))
00217 s++;
00218
00219 if (*s == 0)
00220 return TRUE;
00221
00222 return FALSE;
00223 }
00224
00225
00226
00227
00228
00229
00230 const gchar *
00231 qof_util_whitespace_filter (const gchar * val)
00232 {
00233 size_t len;
00234 if (!val)
00235 return NULL;
00236
00237 len = strspn (val, "\a\b\t\n\v\f\r ");
00238 if (0 == val[len])
00239 return NULL;
00240 return val + len;
00241 }
00242
00243
00244
00245
00246
00247
00248 gint
00249 qof_util_bool_to_int (const gchar * val)
00250 {
00251 const gchar *p = qof_util_whitespace_filter (val);
00252 if (!p)
00253 return 0;
00254 if ('t' == p[0])
00255 return 1;
00256 if ('T' == p[0])
00257 return 1;
00258 if ('y' == p[0])
00259 return 1;
00260 if ('Y' == p[0])
00261 return 1;
00262 if (strstr (p, "true"))
00263 return 1;
00264 if (strstr (p, "TRUE"))
00265 return 1;
00266 if (strstr (p, "yes"))
00267 return 1;
00268 if (strstr (p, "YES"))
00269 return 1;
00270 return atoi (val);
00271 }
00272
00273
00274
00275
00276
00277 gboolean
00278 qof_util_param_edit (QofInstance * inst, const QofParam *param)
00279 {
00280 QofBackend *be;
00281 QofUndo *undo_data;
00282
00283 if (!inst)
00284 return FALSE;
00285 (inst->editlevel)++;
00286 if (1 < inst->editlevel)
00287 return FALSE;
00288 if (0 >= inst->editlevel)
00289 inst->editlevel = 1;
00290 be = qof_book_get_backend (inst->book);
00291 if (param != NULL)
00292 {
00293 undo_data = inst->book->undo_data;
00294 inst->param = param;
00295 if (undo_data->undo_operation_open)
00296 qof_undo_modify (inst, param);
00297 }
00298 if (be && qof_backend_begin_exists (be))
00299 qof_backend_run_begin (be, inst);
00300 else
00301 inst->dirty = TRUE;
00302 return TRUE;
00303 }
00304
00305 gboolean
00306 qof_util_param_commit (QofInstance * inst, const QofParam * param)
00307 {
00308 QofUndo *undo_data;
00309 QofBackend * be;
00310
00311 if (!inst)
00312 return FALSE;
00313 (inst->editlevel)--;
00314 if (0 < inst->editlevel)
00315 return FALSE;
00316 be = qof_book_get_backend (inst->book);
00317 inst->param = param;
00318 if (be && qof_backend_commit_exists (be))
00319 qof_backend_run_commit (be, inst);
00320 if (param != NULL)
00321 {
00322 undo_data = inst->book->undo_data;
00323 if (undo_data->undo_operation_open)
00324 qof_undo_commit (inst, param);
00325 }
00326 return TRUE;
00327 }
00328
00329 gchar *
00330 qof_util_make_utf8 (gchar * string)
00331 {
00332 gchar *value;
00333
00334 if (!string)
00335 return NULL;
00336 if (g_utf8_validate (string, -1, NULL))
00337 return string;
00338 value = g_locale_to_utf8 (string, -1, NULL, NULL, NULL);
00339 if (!value)
00340 {
00341 PWARN (" unable to convert from locale %s", string);
00342 PINFO ("trying to convert from ISO-8859-15.");
00343 value = g_convert (string, -1, "UTF-8", "ISO-8859-15",
00344 NULL, NULL, NULL);
00345 if (!value)
00346 {
00347 PERR (" conversion failed");
00348 return string;
00349 }
00350 return value;
00351 }
00352 return value;
00353 }
00354
00355
00356
00357
00358
00359 static GCache *qof_string_cache = NULL;
00360
00361 #ifdef THESE_CAN_BE_USEFUL_FOR_DEGUGGING
00362 static guint
00363 g_str_hash_KEY (gconstpointer v)
00364 {
00365 return g_str_hash (v);
00366 }
00367
00368 static guint
00369 g_str_hash_VAL (gconstpointer v)
00370 {
00371 return g_str_hash (v);
00372 }
00373
00374 static gpointer
00375 g_strdup_VAL (gpointer v)
00376 {
00377 return g_strdup (v);
00378 }
00379
00380 static gpointer
00381 g_strdup_KEY (gpointer v)
00382 {
00383 return g_strdup (v);
00384 }
00385 static void
00386 g_free_VAL (gpointer v)
00387 {
00388 return g_free (v);
00389 }
00390 static void
00391 g_free_KEY (gpointer v)
00392 {
00393 return g_free (v);
00394 }
00395
00396 static gboolean
00397 qof_util_str_equal (gconstpointer v, gconstpointer v2)
00398 {
00399 return (v && v2) ? g_str_equal (v, v2) : FALSE;
00400 }
00401 #endif
00402 #ifdef QOF_DISABLE_DEPRECATED
00403 static GCache *
00404 qof_util_get_string_cache (void)
00405 #else
00406 GCache *
00407 qof_util_get_string_cache (void)
00408 #endif
00409 {
00410 if (!qof_string_cache)
00411 {
00412 qof_string_cache = g_cache_new ((GCacheNewFunc) g_strdup,
00413 g_free,
00414 (GCacheDupFunc) g_strdup,
00415 g_free,
00416 g_str_hash,
00417 g_str_hash,
00418 g_str_equal);
00419 }
00420 return qof_string_cache;
00421 }
00422
00423 void
00424 qof_util_string_cache_destroy (void)
00425 {
00426 if (qof_string_cache)
00427 g_cache_destroy (qof_string_cache);
00428 qof_string_cache = NULL;
00429 }
00430
00431 void
00432 qof_util_string_cache_remove (gconstpointer key)
00433 {
00434 if (key)
00435 g_cache_remove (qof_util_get_string_cache (), key);
00436 }
00437
00438 gpointer
00439 qof_util_string_cache_insert (gconstpointer key)
00440 {
00441 if (key)
00442 return g_cache_insert(qof_util_get_string_cache(), (gpointer)key);
00443 return NULL;
00444 }
00445
00446 gchar *
00447 qof_util_param_to_string (QofEntity * ent, const QofParam * param)
00448 {
00449 gchar *param_string;
00450 gchar param_sa[GUID_ENCODING_LENGTH + 1];
00451 gboolean known_type;
00452 QofType paramType;
00453 const GUID *param_guid;
00454 QofNumeric param_numeric, (*numeric_getter) (QofEntity *, const QofParam *);
00455 gdouble param_double, (*double_getter) (QofEntity *, const QofParam *);
00456 gboolean param_boolean, (*boolean_getter) (QofEntity *, const QofParam *);
00457 gint32 param_i32, (*int32_getter) (QofEntity *, const QofParam *);
00458 gint64 param_i64, (*int64_getter) (QofEntity *, const QofParam *);
00459 gchar param_char, (*char_getter) (QofEntity *, const QofParam *);
00460
00461 param_string = NULL;
00462 known_type = FALSE;
00463 g_return_val_if_fail (ent && param, NULL);
00464 paramType = param->param_type;
00465 if (safe_strcmp (paramType, QOF_TYPE_STRING) == 0)
00466 {
00467 param_string = g_strdup (param->param_getfcn (ent, param));
00468 if (param_string == NULL)
00469 {
00470 param_string = "";
00471 }
00472 known_type = TRUE;
00473 return param_string;
00474 }
00475 if (safe_strcmp (paramType, QOF_TYPE_TIME) == 0)
00476 {
00477 QofTime *param_qt;
00478 QofDate *qd;
00479 param_qt = param->param_getfcn (ent, param);
00480 qd = qof_date_from_qtime (param_qt);
00481 return qof_date_print (qd, QOF_DATE_FORMAT_UTC);
00482 }
00483 #ifndef QOF_DISABLE_DEPRECATED
00484 if (safe_strcmp (paramType, QOF_TYPE_DATE) == 0)
00485 {
00486 Timespec param_ts, (*date_getter) (QofEntity *, const QofParam *);
00487 time_t param_t;
00488 gchar param_date[MAX_DATE_LENGTH];
00489
00490 date_getter =
00491 (Timespec (*)(QofEntity *, const QofParam *)) param->param_getfcn;
00492 param_ts = date_getter (ent, param);
00493 param_t = param_ts.tv_sec;
00494 strftime (param_date, MAX_DATE_LENGTH,
00495 QOF_UTC_DATE_FORMAT, gmtime (¶m_t));
00496 param_string = g_strdup (param_date);
00497 known_type = TRUE;
00498 return param_string;
00499 }
00500 #endif
00501 if ((safe_strcmp (paramType, QOF_TYPE_NUMERIC) == 0) ||
00502 (safe_strcmp (paramType, QOF_TYPE_DEBCRED) == 0))
00503 {
00504 numeric_getter =
00505 (QofNumeric (*)(QofEntity *, const QofParam *)) param->param_getfcn;
00506 param_numeric = numeric_getter (ent, param);
00507 param_string = g_strdup (qof_numeric_to_string (param_numeric));
00508 known_type = TRUE;
00509 return param_string;
00510 }
00511 if (safe_strcmp (paramType, QOF_TYPE_GUID) == 0)
00512 {
00513 param_guid = param->param_getfcn (ent, param);
00514 guid_to_string_buff (param_guid, param_sa);
00515 param_string = g_strdup (param_sa);
00516 known_type = TRUE;
00517 return param_string;
00518 }
00519 if (safe_strcmp (paramType, QOF_TYPE_INT32) == 0)
00520 {
00521 int32_getter =
00522 (gint32 (*)(QofEntity *, const QofParam *)) param->param_getfcn;
00523 param_i32 = int32_getter (ent, param);
00524 param_string = g_strdup_printf ("%d", param_i32);
00525 known_type = TRUE;
00526 return param_string;
00527 }
00528 if (safe_strcmp (paramType, QOF_TYPE_INT64) == 0)
00529 {
00530 int64_getter =
00531 (gint64 (*)(QofEntity *, const QofParam *)) param->param_getfcn;
00532 param_i64 = int64_getter (ent, param);
00533 param_string = g_strdup_printf ("%" G_GINT64_FORMAT, param_i64);
00534 known_type = TRUE;
00535 return param_string;
00536 }
00537 if (safe_strcmp (paramType, QOF_TYPE_DOUBLE) == 0)
00538 {
00539 double_getter =
00540 (double (*)(QofEntity *, const QofParam *)) param->param_getfcn;
00541 param_double = double_getter (ent, param);
00542 param_string = g_strdup_printf ("%f", param_double);
00543 known_type = TRUE;
00544 return param_string;
00545 }
00546 if (safe_strcmp (paramType, QOF_TYPE_BOOLEAN) == 0)
00547 {
00548 boolean_getter =
00549 (gboolean (*)(QofEntity *, const QofParam *)) param->param_getfcn;
00550 param_boolean = boolean_getter (ent, param);
00551
00552 if (param_boolean == TRUE)
00553 {
00554 param_string = g_strdup ("true");
00555 }
00556 else
00557 {
00558 param_string = g_strdup ("false");
00559 }
00560 known_type = TRUE;
00561 return param_string;
00562 }
00563
00564 if (safe_strcmp (paramType, QOF_TYPE_KVP) == 0)
00565 {
00566 KvpFrame *frame = NULL;
00567 frame = param->param_getfcn (ent, param);
00568 known_type = TRUE;
00569 if (!kvp_frame_is_empty (frame))
00570 {
00571 GHashTable *hash = kvp_frame_get_hash (frame);
00572 param_string = g_strdup_printf ("%s(%d)", QOF_TYPE_KVP,
00573 g_hash_table_size (hash));
00574 }
00575 return param_string;
00576 }
00577 if (safe_strcmp (paramType, QOF_TYPE_CHAR) == 0)
00578 {
00579 char_getter =
00580 (gchar (*)(QofEntity *, const QofParam *)) param->param_getfcn;
00581 param_char = char_getter (ent, param);
00582 known_type = TRUE;
00583 return g_strdup_printf ("%c", param_char);
00584 }
00585
00586 if (safe_strcmp (paramType, QOF_TYPE_COLLECT) == 0)
00587 {
00588 QofCollection *col = NULL;
00589 col = param->param_getfcn (ent, param);
00590 known_type = TRUE;
00591 return g_strdup_printf ("%s(%d)",
00592 qof_collection_get_type (col), qof_collection_count (col));
00593 }
00594 if (safe_strcmp (paramType, QOF_TYPE_CHOICE) == 0)
00595 {
00596 QofEntity *child = NULL;
00597 child = param->param_getfcn (ent, param);
00598 if (!child)
00599 {
00600 return param_string;
00601 }
00602 known_type = TRUE;
00603 return g_strdup (qof_object_printable (child->e_type, child));
00604 }
00605 if (safe_strcmp (paramType, QOF_PARAM_BOOK) == 0)
00606 {
00607 QofBackend *be;
00608 QofBook *book;
00609 book = param->param_getfcn (ent, param);
00610 PINFO (" book param %p", book);
00611 be = qof_book_get_backend (book);
00612 known_type = TRUE;
00613 PINFO (" backend=%p", be);
00614 if (!be)
00615 {
00616 return QOF_PARAM_BOOK;
00617 }
00618 param_string = g_strdup (be->fullpath);
00619 PINFO (" fullpath=%s", param_string);
00620 if (param_string)
00621 {
00622 return param_string;
00623 }
00624 param_guid = qof_entity_get_guid ((QofEntity*)book);
00625 guid_to_string_buff (param_guid, param_sa);
00626 PINFO (" book GUID=%s", param_sa);
00627 param_string = g_strdup (param_sa);
00628 return param_string;
00629 }
00630 if (!known_type)
00631 {
00632 QofEntity *child = NULL;
00633 child = param->param_getfcn (ent, param);
00634 if (!child)
00635 {
00636 return param_string;
00637 }
00638 return g_strdup (qof_object_printable (child->e_type, child));
00639 }
00640 return g_strdup ("");
00641 }
00642
00643 gboolean
00644 qof_util_param_set_string (QofEntity * ent, const QofParam * param,
00645 const gchar * value_string)
00646 {
00647 void (*string_setter) (QofEntity *, const gchar *);
00648 void (*time_setter) (QofEntity *, QofTime *);
00649 void (*numeric_setter) (QofEntity *, QofNumeric);
00650 void (*guid_setter) (QofEntity *, const GUID *);
00651 void (*double_setter) (QofEntity *, gdouble);
00652 void (*boolean_setter) (QofEntity *, gboolean);
00653 void (*i32_setter) (QofEntity *, gint32);
00654 void (*i64_setter) (QofEntity *, gint64);
00655 void (*char_setter) (QofEntity *, gchar);
00656
00657
00658
00659
00660 g_return_val_if_fail (ent, FALSE);
00661 g_return_val_if_fail (param, FALSE);
00662 g_return_val_if_fail (value_string, FALSE);
00663
00664 if (safe_strcmp (param->param_type, QOF_TYPE_STRING) == 0)
00665 {
00666 string_setter =
00667 (void (*)(QofEntity *,
00668 const gchar *)) param->param_setfcn;
00669 if (string_setter != NULL)
00670 string_setter (ent, value_string);
00671
00672 }
00673 if (safe_strcmp (param->param_type, QOF_TYPE_TIME) == 0)
00674 {
00675 QofTime *qt;
00676 QofDate *qd;
00677
00678 qd = qof_date_parse (value_string, QOF_DATE_FORMAT_UTC);
00679 if (!qd)
00680 return FALSE;
00681 qt = qof_date_to_qtime (qd);
00682 time_setter =
00683 (void (*)(QofEntity *, QofTime *))
00684 param->param_setfcn;
00685 if ((time_setter != NULL) && (qof_time_is_valid (qt)))
00686 time_setter (ent, qt);
00687 qof_date_free (qd);
00688
00689 }
00690 #ifndef QOF_DISABLE_DEPRECATED
00691 if (safe_strcmp (param->param_type, QOF_TYPE_DATE) == 0)
00692 {
00693 return FALSE;
00694
00695 }
00696 #endif
00697 if ((safe_strcmp (param->param_type, QOF_TYPE_NUMERIC) == 0) ||
00698 (safe_strcmp (param->param_type, QOF_TYPE_DEBCRED) == 0))
00699 {
00700 QofNumeric num;
00701 numeric_setter =
00702 (void (*)(QofEntity *,
00703 QofNumeric)) param->param_setfcn;
00704 if (!qof_numeric_from_string (value_string, &num) ||
00705 (qof_numeric_check (num) != QOF_ERROR_OK))
00706 return FALSE;
00707 if (numeric_setter != NULL)
00708 numeric_setter (ent, num);
00709
00710 }
00711 if (safe_strcmp (param->param_type, QOF_TYPE_GUID) == 0)
00712 {
00713 GUID * guid;
00714
00715 guid = guid_malloc();
00716 guid_new (guid);
00717 guid_setter =
00718 (void (*)(QofEntity *,
00719 const GUID *)) param->param_setfcn;
00720 if (!string_to_guid(value_string, guid))
00721 return FALSE;
00722 if (guid_setter != NULL)
00723 guid_setter (ent, guid);
00724
00725 }
00726 if (safe_strcmp (param->param_type, QOF_TYPE_INT32) == 0)
00727 {
00728 gint32 i32;
00729 gchar *tail;
00730
00731 errno = 0;
00732 i32_setter =
00733 (void (*)(QofEntity *, gint32)) param->param_setfcn;
00734 i32 =
00735 (gint32) strtol (value_string, &tail, 0);
00736 if ((i32_setter != NULL) && (errno == 0))
00737
00738 i32_setter (ent, i32);
00739
00740 }
00741 if (safe_strcmp (param->param_type, QOF_TYPE_INT64) == 0)
00742 {
00743 gint64 i64;
00744 gchar *tail;
00745
00746 errno = 0;
00747 i64 = strtoll (value_string, &tail, 0);
00748 i64_setter =
00749 (void (*)(QofEntity *, gint64)) param->param_setfcn;
00750 if ((i64_setter != NULL) && (errno == 0))
00751 i64_setter (ent, i64);
00752
00753 }
00754 if (safe_strcmp (param->param_type, QOF_TYPE_DOUBLE) == 0)
00755 {
00756 gdouble db;
00757 gchar *tail;
00758
00759 errno = 0;
00760 db = strtod (value_string, &tail);
00761 double_setter =
00762 (void (*)(QofEntity *, gdouble)) param->param_setfcn;
00763 if ((double_setter != NULL) && (errno == 0))
00764 double_setter (ent, db);
00765
00766 }
00767 if (safe_strcmp (param->param_type, QOF_TYPE_BOOLEAN) == 0)
00768 {
00769 gint val;
00770 gboolean b;
00771
00772 boolean_setter =
00773 (void (*)(QofEntity *, gboolean)) param->param_setfcn;
00774 val = qof_util_bool_to_int(value_string);
00775 if ((val > 1) || (val < 0))
00776 return FALSE;
00777 b = (val == 1) ? TRUE : FALSE;
00778 if (boolean_setter != NULL)
00779 boolean_setter (ent, val);
00780
00781 }
00782 if (safe_strcmp (param->param_type, QOF_TYPE_KVP) == 0)
00783 {
00784
00785 return FALSE;
00786
00787
00788
00789
00790
00791
00792
00793
00794 }
00795 if (safe_strcmp (param->param_type, QOF_TYPE_CHAR) == 0)
00796 {
00797 char_setter =
00798 (void (*)(QofEntity *, gchar)) param->param_setfcn;
00799 if (char_setter != NULL)
00800 char_setter (ent, value_string[0]);
00801
00802 }
00803 if (safe_strcmp (param->param_type, QOF_TYPE_COLLECT) == 0)
00804 {
00805
00806 return FALSE;
00807 }
00808 if (safe_strcmp (param->param_type, QOF_TYPE_CHOICE) == 0)
00809 {
00810
00811 return FALSE;
00812 }
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828 return TRUE;
00829 }
00830
00831
00832 void
00833 qof_init (void)
00834 {
00835 qof_util_get_string_cache ();
00836 guid_init ();
00837 qof_date_init ();
00838 qof_object_initialize ();
00839 qof_query_init ();
00840 qof_book_register ();
00841 }
00842
00843 void
00844 qof_close (void)
00845 {
00846 qof_query_shutdown ();
00847 qof_object_shutdown ();
00848 guid_shutdown ();
00849 qof_date_close ();
00850 qof_util_string_cache_destroy ();
00851 }
00852
00853