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