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 <ctype.h>
00031 #include <glib.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include "qof.h"
00035
00036 static QofLogModule log_module = QOF_MOD_UTIL;
00037
00038
00039
00040 gchar *
00041 strncasestr (const guchar * str1, const guchar * str2, size_t len)
00042 {
00043 while (*str1 && len--)
00044 {
00045 if (toupper (*str1) == toupper (*str2))
00046 {
00047 if (strncasecmp (str1, str2, strlen (str2)) == 0)
00048 return (gchar *) str1;
00049 }
00050 str1++;
00051 }
00052 return NULL;
00053 }
00054
00055 #ifndef HAVE_STRCASESTR
00056
00057
00058 gchar *
00059 strcasestr (const gchar * str1, const gchar * str2)
00060 {
00061 size_t len = strlen (str1);
00062 gchar *retval = strncasestr (str1, str2, len);
00063 return retval;
00064 }
00065 #endif
00066
00067 gint
00068 safe_strcmp (const gchar * da, const gchar * db)
00069 {
00070 if ((da) && (db))
00071 {
00072 if ((da) != (db))
00073 {
00074 gint retval = strcmp ((da), (db));
00075
00076 if (retval)
00077 return retval;
00078 }
00079 }
00080 else if ((!(da)) && (db))
00081 return -1;
00082 else if ((da) && (!(db)))
00083 return +1;
00084 return 0;
00085 }
00086
00087 gint
00088 safe_strcasecmp (const gchar * da, const gchar * db)
00089 {
00090 if ((da) && (db))
00091 {
00092 if ((da) != (db))
00093 {
00094 gint retval = strcasecmp ((da), (db));
00095
00096 if (retval)
00097 return retval;
00098 }
00099 }
00100 else if ((!(da)) && (db))
00101 return -1;
00102 else if ((da) && (!(db)))
00103 return +1;
00104 return 0;
00105 }
00106
00107 gint
00108 null_strcmp (const gchar * da, const gchar * db)
00109 {
00110 if (da && db)
00111 return strcmp (da, db);
00112 if (!da && db && 0 == db[0])
00113 return 0;
00114 if (!db && da && 0 == da[0])
00115 return 0;
00116 if (!da && db)
00117 return -1;
00118 if (da && !db)
00119 return +1;
00120 return 0;
00121 }
00122
00123 #define MAX_DIGITS 50
00124
00125
00126 gchar *
00127 ultostr (gulong val, gint base)
00128 {
00129 gchar buf[MAX_DIGITS];
00130 gulong broke[MAX_DIGITS];
00131 gint i;
00132 gulong places = 0, reval;
00133
00134 if ((2 > base) || (36 < base))
00135 return NULL;
00136
00137
00138 places = 0;
00139 for (i = 0; i < MAX_DIGITS; i++)
00140 {
00141 broke[i] = val;
00142 places++;
00143 val /= base;
00144 if (0 == val)
00145 break;
00146 }
00147
00148
00149 reval = 0;
00150 for (i = places - 2; i >= 0; i--)
00151 {
00152 reval += broke[i + 1];
00153 reval *= base;
00154 broke[i] -= reval;
00155 }
00156
00157
00158 for (i = 0; i < (gint) places; i++)
00159 {
00160 if (10 > broke[i])
00161 {
00162 buf[places - 1 - i] = 0x30 + broke[i];
00163 }
00164 else
00165 {
00166 buf[places - 1 - i] = 0x41 - 10 + broke[i];
00167 }
00168 }
00169 buf[places] = 0x0;
00170
00171 return g_strdup (buf);
00172 }
00173
00174
00175
00176
00177
00178 gboolean
00179 qof_util_string_isnum (const guchar * s)
00180 {
00181 if (s == NULL)
00182 return FALSE;
00183 if (*s == 0)
00184 return FALSE;
00185
00186 while (*s && isspace (*s))
00187 s++;
00188
00189 if (*s == 0)
00190 return FALSE;
00191 if (!isdigit (*s))
00192 return FALSE;
00193
00194 while (*s && isdigit (*s))
00195 s++;
00196
00197 if (*s == 0)
00198 return TRUE;
00199
00200 while (*s && isspace (*s))
00201 s++;
00202
00203 if (*s == 0)
00204 return TRUE;
00205
00206 return FALSE;
00207 }
00208
00209
00210
00211
00212
00213
00214 const gchar *
00215 qof_util_whitespace_filter (const gchar * val)
00216 {
00217 size_t len;
00218 if (!val)
00219 return NULL;
00220
00221 len = strspn (val, "\a\b\t\n\v\f\r ");
00222 if (0 == val[len])
00223 return NULL;
00224 return val + len;
00225 }
00226
00227
00228
00229
00230
00231
00232 gint
00233 qof_util_bool_to_int (const gchar * val)
00234 {
00235 const gchar *p = qof_util_whitespace_filter (val);
00236 if (!p)
00237 return 0;
00238 if ('t' == p[0])
00239 return 1;
00240 if ('T' == p[0])
00241 return 1;
00242 if ('y' == p[0])
00243 return 1;
00244 if ('Y' == p[0])
00245 return 1;
00246 if (strstr (p, "true"))
00247 return 1;
00248 if (strstr (p, "TRUE"))
00249 return 1;
00250 if (strstr (p, "yes"))
00251 return 1;
00252 if (strstr (p, "YES"))
00253 return 1;
00254 return atoi (val);
00255 }
00256
00257
00258
00259
00260
00261 gboolean
00262 qof_begin_edit (QofInstance * inst)
00263 {
00264 QofBackend *be;
00265
00266 if (!inst)
00267 return FALSE;
00268 (inst->editlevel)++;
00269 if (1 < inst->editlevel)
00270 return FALSE;
00271 if (0 >= inst->editlevel)
00272 inst->editlevel = 1;
00273 be = qof_book_get_backend (inst->book);
00274 if (be && qof_backend_begin_exists (be))
00275 qof_backend_run_begin (be, inst);
00276 else
00277 inst->dirty = TRUE;
00278 return TRUE;
00279 }
00280
00281 gboolean
00282 qof_commit_edit (QofInstance * inst)
00283 {
00284 QofBackend *be;
00285
00286 if (!inst)
00287 return FALSE;
00288 (inst->editlevel)--;
00289 if (0 < inst->editlevel)
00290 return FALSE;
00291 if ((-1 == inst->editlevel) && inst->dirty)
00292 {
00293 be = qof_book_get_backend ((inst)->book);
00294 if (be && qof_backend_begin_exists (be))
00295 qof_backend_run_begin (be, inst);
00296 inst->editlevel = 0;
00297 }
00298 if (0 > inst->editlevel)
00299 inst->editlevel = 0;
00300 return TRUE;
00301 }
00302
00303
00304 gboolean
00305 qof_commit_edit_part2 (QofInstance * inst,
00306 void (*on_error) (QofInstance *, QofBackendError),
00307 void (*on_done) (QofInstance *), void (*on_free) (QofInstance *))
00308 {
00309 QofBackend *be;
00310
00311
00312 be = qof_book_get_backend (inst->book);
00313 if (be && qof_backend_commit_exists (be))
00314 {
00315 QofBackendError errcode;
00316
00317
00318 do
00319 {
00320 errcode = qof_backend_get_error (be);
00321 }
00322 while (ERR_BACKEND_NO_ERR != errcode);
00323
00324 qof_backend_run_commit (be, inst);
00325 errcode = qof_backend_get_error (be);
00326 if (ERR_BACKEND_NO_ERR != errcode)
00327 {
00328
00329 inst->do_free = FALSE;
00330
00331
00332 qof_backend_set_error (be, errcode);
00333 if (on_error)
00334 on_error (inst, errcode);
00335 return FALSE;
00336 }
00337
00338 inst->dirty = FALSE;
00339 }
00340 if (inst->do_free)
00341 {
00342 if (on_free)
00343 on_free (inst);
00344 return TRUE;
00345 }
00346 if (on_done)
00347 on_done (inst);
00348 return TRUE;
00349 }
00350
00351
00352
00353
00354
00355 static GCache *qof_string_cache = NULL;
00356
00357 #ifdef THESE_CAN_BE_USEFUL_FOR_DEGUGGING
00358 static guint
00359 g_str_hash_KEY (gconstpointer v)
00360 {
00361 return g_str_hash (v);
00362 }
00363
00364 static guint
00365 g_str_hash_VAL (gconstpointer v)
00366 {
00367 return g_str_hash (v);
00368 }
00369
00370 static gpointer
00371 g_strdup_VAL (gpointer v)
00372 {
00373 return g_strdup (v);
00374 }
00375
00376 static gpointer
00377 g_strdup_KEY (gpointer v)
00378 {
00379 return g_strdup (v);
00380 }
00381 static void
00382 g_free_VAL (gpointer v)
00383 {
00384 return g_free (v);
00385 }
00386 static void
00387 g_free_KEY (gpointer v)
00388 {
00389 return g_free (v);
00390 }
00391
00392 static gboolean
00393 qof_util_str_equal (gconstpointer v, gconstpointer v2)
00394 {
00395 return (v && v2) ? g_str_equal (v, v2) : FALSE;
00396 }
00397 #endif
00398 #ifdef QOF_DISABLE_DEPRECATED
00399 static GCache *
00400 qof_util_get_string_cache (void)
00401 #else
00402 GCache *
00403 qof_util_get_string_cache (void)
00404 #endif
00405 {
00406 if (!qof_string_cache)
00407 {
00408 qof_string_cache = g_cache_new ((GCacheNewFunc) g_strdup,
00409 g_free,
00410 (GCacheDupFunc) g_strdup,
00411 g_free,
00412 g_str_hash,
00413 g_str_hash,
00414 g_str_equal);
00415 }
00416 return qof_string_cache;
00417 }
00418
00419 void
00420 qof_util_string_cache_destroy (void)
00421 {
00422 if (qof_string_cache)
00423 g_cache_destroy (qof_string_cache);
00424 qof_string_cache = NULL;
00425 }
00426
00427 void
00428 qof_util_string_cache_remove (gconstpointer key)
00429 {
00430 if (key)
00431 g_cache_remove (qof_util_get_string_cache (), key);
00432 }
00433
00434 gpointer
00435 qof_util_string_cache_insert (gconstpointer key)
00436 {
00437 if (key)
00438 return g_cache_insert (qof_util_get_string_cache (),
00439 (gpointer) key);
00440 return NULL;
00441 }
00442
00443 gchar *
00444 qof_util_param_as_string (QofEntity * ent, QofParam * param)
00445 {
00446 gchar *param_string;
00447 gchar param_sa[GUID_ENCODING_LENGTH + 1];
00448 gboolean known_type;
00449 QofType paramType;
00450 const GUID *param_guid;
00451 gnc_numeric param_numeric, (*numeric_getter) (QofEntity *, QofParam *);
00452 double param_double, (*double_getter) (QofEntity *, QofParam *);
00453 gboolean param_boolean, (*boolean_getter) (QofEntity *, QofParam *);
00454 gint32 param_i32, (*int32_getter) (QofEntity *, QofParam *);
00455 gint64 param_i64, (*int64_getter) (QofEntity *, QofParam *);
00456 gchar param_char, (*char_getter) (QofEntity *, QofParam *);
00457
00458 param_string = NULL;
00459 known_type = FALSE;
00460 paramType = param->param_type;
00461 if (safe_strcmp (paramType, QOF_TYPE_STRING) == 0)
00462 {
00463 param_string = g_strdup (param->param_getfcn (ent, param));
00464 if (param_string == NULL)
00465 {
00466 param_string = "";
00467 }
00468 known_type = TRUE;
00469 return param_string;
00470 }
00471 if (safe_strcmp (paramType, QOF_TYPE_TIME) == 0)
00472 {
00473 QofTime *param_qt;
00474 QofDate *qd;
00475 param_qt = param->param_getfcn (ent, param);
00476 qd = qof_date_from_qtime (param_qt);
00477 return qof_date_print (qd, QOF_DATE_FORMAT_UTC);
00478 }
00479 #ifndef QOF_DISABLE_DEPRECATED
00480 if (safe_strcmp (paramType, QOF_TYPE_DATE) == 0)
00481 {
00482 Timespec param_ts, (*date_getter) (QofEntity *, QofParam *);
00483 time_t param_t;
00484 gchar param_date[MAX_DATE_LENGTH];
00485
00486 date_getter =
00487 (Timespec (*)(QofEntity *, QofParam *)) param->param_getfcn;
00488 param_ts = date_getter (ent, param);
00489 param_t = param_ts.tv_sec;
00490 strftime (param_date, MAX_DATE_LENGTH,
00491 QOF_UTC_DATE_FORMAT, gmtime (¶m_t));
00492 param_string = g_strdup (param_date);
00493 known_type = TRUE;
00494 return param_string;
00495 }
00496 #endif
00497 if ((safe_strcmp (paramType, QOF_TYPE_NUMERIC) == 0) ||
00498 (safe_strcmp (paramType, QOF_TYPE_DEBCRED) == 0))
00499 {
00500 numeric_getter =
00501 (gnc_numeric (*)(QofEntity *, QofParam *)) param->param_getfcn;
00502 param_numeric = numeric_getter (ent, param);
00503 param_string = g_strdup (gnc_numeric_to_string (param_numeric));
00504 known_type = TRUE;
00505 return param_string;
00506 }
00507 if (safe_strcmp (paramType, QOF_TYPE_GUID) == 0)
00508 {
00509 param_guid = param->param_getfcn (ent, param);
00510 guid_to_string_buff (param_guid, param_sa);
00511 param_string = g_strdup (param_sa);
00512 known_type = TRUE;
00513 return param_string;
00514 }
00515 if (safe_strcmp (paramType, QOF_TYPE_INT32) == 0)
00516 {
00517 int32_getter =
00518 (gint32 (*)(QofEntity *, QofParam *)) param->param_getfcn;
00519 param_i32 = int32_getter (ent, param);
00520 param_string = g_strdup_printf ("%d", param_i32);
00521 known_type = TRUE;
00522 return param_string;
00523 }
00524 if (safe_strcmp (paramType, QOF_TYPE_INT64) == 0)
00525 {
00526 int64_getter =
00527 (gint64 (*)(QofEntity *, QofParam *)) param->param_getfcn;
00528 param_i64 = int64_getter (ent, param);
00529 param_string = g_strdup_printf ("%" G_GINT64_FORMAT, param_i64);
00530 known_type = TRUE;
00531 return param_string;
00532 }
00533 if (safe_strcmp (paramType, QOF_TYPE_DOUBLE) == 0)
00534 {
00535 double_getter =
00536 (double (*)(QofEntity *, QofParam *)) param->param_getfcn;
00537 param_double = double_getter (ent, param);
00538 param_string = g_strdup_printf ("%f", param_double);
00539 known_type = TRUE;
00540 return param_string;
00541 }
00542 if (safe_strcmp (paramType, QOF_TYPE_BOOLEAN) == 0)
00543 {
00544 boolean_getter =
00545 (gboolean (*)(QofEntity *, QofParam *)) param->param_getfcn;
00546 param_boolean = boolean_getter (ent, param);
00547
00548 if (param_boolean == TRUE)
00549 {
00550 param_string = g_strdup ("true");
00551 }
00552 else
00553 {
00554 param_string = g_strdup ("false");
00555 }
00556 known_type = TRUE;
00557 return param_string;
00558 }
00559
00560 if (safe_strcmp (paramType, QOF_TYPE_KVP) == 0)
00561 {
00562 KvpFrame *frame = NULL;
00563 frame = param->param_getfcn (ent, param);
00564 known_type = TRUE;
00565 if (!kvp_frame_is_empty (frame))
00566 {
00567 GHashTable *hash = kvp_frame_get_hash (frame);
00568 param_string = g_strdup_printf ("%s(%d)", QOF_TYPE_KVP,
00569 g_hash_table_size (hash));
00570 }
00571 return param_string;
00572 }
00573 if (safe_strcmp (paramType, QOF_TYPE_CHAR) == 0)
00574 {
00575 char_getter =
00576 (gchar (*)(QofEntity *, QofParam *)) param->param_getfcn;
00577 param_char = char_getter (ent, param);
00578 known_type = TRUE;
00579 return g_strdup_printf ("%c", param_char);
00580 }
00581
00582 if (safe_strcmp (paramType, QOF_TYPE_COLLECT) == 0)
00583 {
00584 QofCollection *col = NULL;
00585 col = param->param_getfcn (ent, param);
00586 known_type = TRUE;
00587 return g_strdup_printf ("%s(%d)",
00588 qof_collection_get_type (col), qof_collection_count (col));
00589 }
00590 if (safe_strcmp (paramType, QOF_TYPE_CHOICE) == 0)
00591 {
00592 QofEntity *child = NULL;
00593 child = param->param_getfcn (ent, param);
00594 if (!child)
00595 {
00596 return param_string;
00597 }
00598 known_type = TRUE;
00599 return g_strdup (qof_object_printable (child->e_type, child));
00600 }
00601 if (safe_strcmp (paramType, QOF_PARAM_BOOK) == 0)
00602 {
00603 QofBackend *be;
00604 QofBook *book;
00605 book = param->param_getfcn (ent, param);
00606 PINFO (" book param %p", book);
00607 be = qof_book_get_backend (book);
00608 known_type = TRUE;
00609 PINFO (" backend=%p", be);
00610 if (!be)
00611 {
00612 return QOF_PARAM_BOOK;
00613 }
00614 param_string = g_strdup (be->fullpath);
00615 PINFO (" fullpath=%s", param_string);
00616 if (param_string)
00617 {
00618 return param_string;
00619 }
00620 param_guid = qof_entity_get_guid ((QofEntity*)book);
00621 guid_to_string_buff (param_guid, param_sa);
00622 PINFO (" book GUID=%s", param_sa);
00623 param_string = g_strdup (param_sa);
00624 return param_string;
00625 }
00626 if (!known_type)
00627 {
00628 QofEntity *child = NULL;
00629 child = param->param_getfcn (ent, param);
00630 if (!child)
00631 {
00632 return param_string;
00633 }
00634 return g_strdup (qof_object_printable (child->e_type, child));
00635 }
00636 return g_strdup ("");
00637 }
00638
00639 void
00640 qof_init (void)
00641 {
00642 qof_util_get_string_cache ();
00643 guid_init ();
00644 qof_date_init ();
00645 qof_object_initialize ();
00646 qof_query_init ();
00647 qof_book_register ();
00648 }
00649
00650 void
00651 qof_close (void)
00652 {
00653 qof_query_shutdown ();
00654 qof_object_shutdown ();
00655 guid_shutdown ();
00656 qof_date_close ();
00657 qof_util_string_cache_destroy ();
00658 }
00659
00660