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