QOF  0.7.5
Utilities: Miscellany

Files

file  qofutil.h
 QOF utility functions.
 

Macros

#define QOF_SCANF_LLD   "%qd"
 
#define QOF_MOD_UTIL   "qof-utilities"
 
#define stpcpy   g_stpcpy
 omitted if stpcpy exists.
 
#define CACHE_INSERT(str)   qof_util_string_cache_insert((gconstpointer)(str))
 
#define CACHE_REMOVE(str)   qof_util_string_cache_remove((str))
 
#define CACHE_REPLACE(dst, src)
 
#define QOF_CACHE_NEW(void)   qof_util_string_cache_insert("")
 

Functions

gint safe_strcmp (const gchar *da, const gchar *db)
 
gint safe_strcasecmp (const gchar *da, const gchar *db)
 
gint null_strcmp (const gchar *da, const gchar *db)
 
gchar * strncasestr (const guchar *str1, const guchar *str2, size_t len)
 
gchar * strcasestr (const gchar *str1, const gchar *str2)
 
gchar * ultostr (gulong val, gint base)
 
gboolean qof_util_string_isnum (const guchar *s)
 
gint qof_util_double_compare (gdouble v1, gdouble v2)
 Compare two gdouble values.
 
const gchar * qof_util_whitespace_filter (const gchar *val)
 
gint qof_util_bool_to_int (const gchar *val)
 
gchar * qof_util_param_to_string (QofEntity *ent, const QofParam *param)
 Converts a parameter to a string for storage or display. More...
 
gboolean qof_util_param_set_string (QofEntity *ent, const QofParam *param, const gchar *value_string)
 Set a parameter from a value string. More...
 
gchar * qof_util_make_utf8 (gchar *string)
 Convert strings received from the wrapped objects into UTF-8. More...
 
void qof_util_string_cache_destroy (void)
 
void qof_util_string_cache_remove (gconstpointer key)
 
gpointer qof_util_string_cache_insert (gconstpointer key)
 
gboolean qof_util_param_edit (QofInstance *inst, const QofParam *param)
 Prepare to edit a parameter. More...
 
gboolean qof_util_param_commit (QofInstance *inst, const QofParam *param)
 Commit this parameter change, with undo support. More...
 

typedef enum as string macros

#define ENUM_BODY(name, value)   name value,
 
#define AS_STRING_CASE(name, value)   case name: { return #name; }
 
#define FROM_STRING_CASE(name, value)
 
#define DEFINE_ENUM(name, list)
 
#define AS_STRING_DEC(name, list)   const gchar* name##asString(name n);
 
#define AS_STRING_FUNC(name, list)
 
#define FROM_STRING_DEC(name, list)
 
#define FROM_STRING_FUNC(name, list)
 

enum as string with no typedef

Similar but used when the enum is NOT a typedef Make sure you use the DEFINE_ENUM_NON_TYPEDEF macro.

You can precede the FROM_STRING_FUNC_NON_TYPEDEF and AS_STRING_FUNC_NON_TYPEDEF macros with the keyword static if appropriate.

ENUM_BODY is used in both types.

#define DEFINE_ENUM_NON_TYPEDEF(name, list)
 
#define FROM_STRING_DEC_NON_TYPEDEF(name, list)
 
#define FROM_STRING_CASE_NON_TYPEDEF(name, value)   if (strcmp(str, #name) == 0) { *type = name; }
 
#define FROM_STRING_FUNC_NON_TYPEDEF(name, list)
 
#define AS_STRING_DEC_NON_TYPEDEF(name, list)   const gchar* name##asString(enum name n);
 
#define AS_STRING_FUNC_NON_TYPEDEF(name, list)
 
#define AS_STRING_CASE_NON_TYPEDEF(name, value)   case name: { return #name; }
 

Convenience wrappers

void qof_init (void)
 Initialise the Query Object Framework. More...
 
void qof_close (void)
 Safely close down the Query Object Framework. More...
 

Detailed Description

Macro Definition Documentation

#define AS_STRING_FUNC (   name,
  list 
)
Value:
const gchar* name##asString(name n) { \
switch (n) { \
list(AS_STRING_CASE) \
default: return ""; } }

Definition at line 73 of file qofutil.h.

#define AS_STRING_FUNC_NON_TYPEDEF (   name,
  list 
)
Value:
const gchar* name##asString(enum name n) { \
switch (n) { \
list(AS_STRING_CASE_NON_TYPEDEF) \
default: return ""; } }

Definition at line 126 of file qofutil.h.

#define CACHE_REPLACE (   dst,
  src 
)
Value:
do { \
gpointer tmp = CACHE_INSERT((src)); \
CACHE_REMOVE((dst)); \
(dst) = tmp; \
} while (0)

Definition at line 330 of file qofutil.h.

#define DEFINE_ENUM (   name,
  list 
)
Value:
typedef enum { \
list(ENUM_BODY) \
}name;

Definition at line 65 of file qofutil.h.

#define DEFINE_ENUM_NON_TYPEDEF (   name,
  list 
)
Value:
enum name { \
list(ENUM_BODY) \
};

Definition at line 105 of file qofutil.h.

#define FROM_STRING_CASE (   name,
  value 
)
Value:
if (strcmp(str, #name) == 0) { \
return name; }

Definition at line 61 of file qofutil.h.

#define FROM_STRING_DEC (   name,
  list 
)
Value:
name name##fromString \
(const gchar* str);

Definition at line 79 of file qofutil.h.

#define FROM_STRING_DEC_NON_TYPEDEF (   name,
  list 
)
Value:
void name##fromString \
(const gchar* str, enum name *type);

Definition at line 110 of file qofutil.h.

#define FROM_STRING_FUNC (   name,
  list 
)
Value:
name name##fromString \
(const gchar* str) { \
if(str == NULL) { return 0; } \
list(FROM_STRING_CASE) \
return 0; }

Definition at line 83 of file qofutil.h.

#define FROM_STRING_FUNC_NON_TYPEDEF (   name,
  list 
)
Value:
void name##fromString \
(const gchar* str, enum name *type) { \
if(str == NULL) { return; } \
list(FROM_STRING_CASE_NON_TYPEDEF) }

Definition at line 117 of file qofutil.h.

#define QOF_SCANF_LLD   "%qd"

Do not use these for printf, only scanf

Definition at line 47 of file qofutil.h.

Function Documentation

gint null_strcmp ( const gchar *  da,
const gchar *  db 
)
inline

The null_strcmp compares strings a and b the same way that strcmp() does, except that either may be null. This routine assumes that a null string is equal to the empty string.

Definition at line 112 of file qofutil.c.

113 {
114  if (da && db)
115  return strcmp (da, db);
116  if (!da && db && 0 == db[0])
117  return 0;
118  if (!db && da && 0 == da[0])
119  return 0;
120  if (!da && db)
121  return -1;
122  if (da && !db)
123  return +1;
124  return 0;
125 }
void qof_close ( void  )

Safely close down the Query Object Framework.

Use in place of separate close / shutdown functions (like guid_shutdown(), qof_query_shutdown() etc.) to protect against future changes.

Definition at line 844 of file qofutil.c.

845 {
846  qof_query_shutdown ();
847  qof_object_shutdown ();
848  guid_shutdown ();
849  qof_date_close ();
851 }
void qof_init ( void  )

Initialise the Query Object Framework.

Use in place of separate init functions (like guid_init() and qof_query_init() etc.) to protect against future changes.

Definition at line 833 of file qofutil.c.

834 {
836  guid_init ();
837  qof_date_init ();
838  qof_object_initialize ();
839  qof_query_init ();
841 }
gint qof_util_bool_to_int ( const gchar *  val)

Return integer 1 if the string starts with 't' or 'T' or contains the word 'true' or 'TRUE'; if string is a number, return that number. (Leading whitespace is ignored).

Definition at line 249 of file qofutil.c.

250 {
251  const gchar *p = qof_util_whitespace_filter (val);
252  if (!p)
253  return 0;
254  if ('t' == p[0])
255  return 1;
256  if ('T' == p[0])
257  return 1;
258  if ('y' == p[0])
259  return 1;
260  if ('Y' == p[0])
261  return 1;
262  if (strstr (p, "true"))
263  return 1;
264  if (strstr (p, "TRUE"))
265  return 1;
266  if (strstr (p, "yes"))
267  return 1;
268  if (strstr (p, "YES"))
269  return 1;
270  return atoi (val);
271 }
gchar* qof_util_make_utf8 ( gchar *  string)

Convert strings received from the wrapped objects into UTF-8.

A wrapper for g_locale_to_utf8 that removes the extra arguments. If the string is already valid UTF-8, it is returned unchanged.

Returns
the converted string or the original, unchanged, string on error or if the string is already UTF-8.

Definition at line 330 of file qofutil.c.

331 {
332  gchar *value;
333 
334  if (!string)
335  return NULL;
336  if (g_utf8_validate (string, -1, NULL))
337  return string;
338  value = g_locale_to_utf8 (string, -1, NULL, NULL, NULL);
339  if (!value)
340  {
341  PWARN (" unable to convert from locale %s", string);
342  PINFO ("trying to convert from ISO-8859-15.");
343  value = g_convert (string, -1, "UTF-8", "ISO-8859-15",
344  NULL, NULL, NULL);
345  if (!value)
346  {
347  PERR (" conversion failed");
348  return string;
349  }
350  return value;
351  }
352  return value;
353 }
gboolean qof_util_param_commit ( QofInstance inst,
const QofParam param 
)

Commit this parameter change, with undo support.

Calls the commit() routine of the backend to commit an edit. If an undo operation has been started, also maintains the undo record so the change can be undone.

param_name can only be NULL if the QofSQLite backend is not in use.

Parameters
instThe QofInstance.
paramThe parameter being modified.
Returns
FALSE on error, otherwise TRUE.

Definition at line 306 of file qofutil.c.

307 {
308  QofUndo *undo_data;
309  QofBackend * be;
310 
311  if (!inst)
312  return FALSE;
313  (inst->editlevel)--;
314  if (0 < inst->editlevel)
315  return FALSE;
316  be = qof_book_get_backend (inst->book);
317  inst->param = param;
318  if (be && qof_backend_commit_exists (be))
319  qof_backend_run_commit (be, inst);
320  if (param != NULL)
321  {
322  undo_data = inst->book->undo_data;
323  if (undo_data->undo_operation_open)
324  qof_undo_commit (inst, param);
325  }
326  return TRUE;
327 }
gboolean qof_util_param_edit ( QofInstance inst,
const QofParam param 
)

Prepare to edit a parameter.

Calls the begin() routine of the backend to prepare for an edit. If an undo operation has been started, also prepares an undo record.

param_name can only be NULL if the QofSQLite backend is not in use.

Note
The intention is that preparing and committing parameter changes is done outside the object using QofParam->param_setfcn but objects can obtain the QofParam themselves if preferred.

Making parameter changes using qof_util_param_edit and qof_util_param_commit makes for simpler QofUndo code because the undo handlers are called implicitly.

qof_book_start_operation (book, "edit PARAM_X");
param = qof_class_get_parameter(OBJ_TYPE, PARAM_NAME);
retbool = qof_util_param_edit (inst, param);
if (retbool)
    param->param_setfcn(ent, value);
retbool = qof_util_param_commit (inst, param);
Parameters
instThe QofInstance.
paramThe parameter being modified.
Returns
FALSE on error, otherwise TRUE.

Definition at line 278 of file qofutil.c.

279 {
280  QofBackend *be;
281  QofUndo *undo_data;
282 
283  if (!inst)
284  return FALSE;
285  (inst->editlevel)++;
286  if (1 < inst->editlevel)
287  return FALSE;
288  if (0 >= inst->editlevel)
289  inst->editlevel = 1;
290  be = qof_book_get_backend (inst->book);
291  if (param != NULL)
292  {
293  undo_data = inst->book->undo_data;
294  inst->param = param;
295  if (undo_data->undo_operation_open)
296  qof_undo_modify (inst, param);
297  }
298  if (be && qof_backend_begin_exists (be))
299  qof_backend_run_begin (be, inst);
300  else
301  inst->dirty = TRUE;
302  return TRUE;
303 }
gboolean qof_util_param_set_string ( QofEntity ent,
const QofParam param,
const gchar *  value_string 
)

Set a parameter from a value string.

Used by string-based backends to set a value from a string previously written out to storage.

The string must be the same format as produced by qof_util_param_to_string for the same parameter type.

Parameters
entThe entity in which the value is to be set.
paramThe parameter that stores the value.
value_stringA string of exactly the same format as produced by qof_util_param_to_string for the parameter type.

e.g. a numeric type would require a string like 50/100 and a time type would require a UTC date stamp like 1907-10-07T03:34:29Z

Returns
FALSE if the string does not match the required type or cannot be set, TRUE on success.

< secondary collections are used for one-to-many references between entities and are implemented using QofCollection. These are NOT the same as the main collections in the QofBook. -# Each QofCollection contains one or many entities - all of a single type. -# The entity type within the collection can be determined at run time. -# Easy conversions to GList or whatever in the param_setfcn handler. -# Each parameter can have its own collection. -# Each entity can have a different type of collection to its siblings, provided that it is acceptable to the set function. -# Each object decides which types are acceptable for which parameter in the set functions. This is then part of the API for that object. QOF_TYPE_COLLECT has two functions, both related to one-to-many links: - Represent a reference between 2 entities with a list of acceptable types. (one object linked to many types of single entities) - Represent a reference between one entity and many entities of another type. (one object linked to many entities of a single type.) If the set function can handle it, it could also be used for true one-to-many links: one object linked to many entities of many types. n.b. Always subject to each collection holding only one type at runtime. (otherwise use books).

Definition at line 644 of file qofutil.c.

646 {
647  void (*string_setter) (QofEntity *, const gchar *);
648  void (*time_setter) (QofEntity *, QofTime *);
649  void (*numeric_setter) (QofEntity *, QofNumeric);
650  void (*guid_setter) (QofEntity *, const GUID *);
651  void (*double_setter) (QofEntity *, gdouble);
652  void (*boolean_setter) (QofEntity *, gboolean);
653  void (*i32_setter) (QofEntity *, gint32);
654  void (*i64_setter) (QofEntity *, gint64);
655  void (*char_setter) (QofEntity *, gchar);
656 /* void (*kvp_frame_setter) (QofEntity *, KvpFrame *);
657  void (*reference_setter) (QofEntity *, QofEntity *);
658  void (*collection_setter) (QofEntity *, QofCollection *);*/
659 
660  g_return_val_if_fail (ent, FALSE);
661  g_return_val_if_fail (param, FALSE);
662  g_return_val_if_fail (value_string, FALSE);
663 
664  if (safe_strcmp (param->param_type, QOF_TYPE_STRING) == 0)
665  {
666  string_setter =
667  (void (*)(QofEntity *,
668  const gchar *)) param->param_setfcn;
669  if (string_setter != NULL)
670  string_setter (ent, value_string);
671 // registered_type = TRUE;
672  }
673  if (safe_strcmp (param->param_type, QOF_TYPE_TIME) == 0)
674  {
675  QofTime *qt;
676  QofDate *qd;
677 
678  qd = qof_date_parse (value_string, QOF_DATE_FORMAT_UTC);
679  if (!qd)
680  return FALSE;
681  qt = qof_date_to_qtime (qd);
682  time_setter =
683  (void (*)(QofEntity *, QofTime *))
684  param->param_setfcn;
685  if ((time_setter != NULL) && (qof_time_is_valid (qt)))
686  time_setter (ent, qt);
687  qof_date_free (qd);
688 // registered_type = TRUE;
689  }
690 #ifndef QOF_DISABLE_DEPRECATED
691  if (safe_strcmp (param->param_type, QOF_TYPE_DATE) == 0)
692  {
693  return FALSE;
694 // registered_type = TRUE;
695  }
696 #endif
697  if ((safe_strcmp (param->param_type, QOF_TYPE_NUMERIC) == 0) ||
698  (safe_strcmp (param->param_type, QOF_TYPE_DEBCRED) == 0))
699  {
700  QofNumeric num;
701  numeric_setter =
702  (void (*)(QofEntity *,
703  QofNumeric)) param->param_setfcn;
704  if (!qof_numeric_from_string (value_string, &num) ||
705  (qof_numeric_check (num) != QOF_ERROR_OK))
706  return FALSE;
707  if (numeric_setter != NULL)
708  numeric_setter (ent, num);
709 // registered_type = TRUE;
710  }
711  if (safe_strcmp (param->param_type, QOF_TYPE_GUID) == 0)
712  {
713  GUID * guid;
714 
715  guid = guid_malloc();
716  guid_new (guid);
717  guid_setter =
718  (void (*)(QofEntity *,
719  const GUID *)) param->param_setfcn;
720  if (!string_to_guid(value_string, guid))
721  return FALSE;
722  if (guid_setter != NULL)
723  guid_setter (ent, guid);
724 // registered_type = TRUE;
725  }
726  if (safe_strcmp (param->param_type, QOF_TYPE_INT32) == 0)
727  {
728  gint32 i32;
729  gchar *tail;
730 
731  errno = 0;
732  i32_setter =
733  (void (*)(QofEntity *, gint32)) param->param_setfcn;
734  i32 =
735  (gint32) strtol (value_string, &tail, 0);
736  if ((i32_setter != NULL) && (errno == 0))
737 
738  i32_setter (ent, i32);
739 // registered_type = TRUE;
740  }
741  if (safe_strcmp (param->param_type, QOF_TYPE_INT64) == 0)
742  {
743  gint64 i64;
744  gchar *tail;
745 
746  errno = 0;
747  i64 = strtoll (value_string, &tail, 0);
748  i64_setter =
749  (void (*)(QofEntity *, gint64)) param->param_setfcn;
750  if ((i64_setter != NULL) && (errno == 0))
751  i64_setter (ent, i64);
752 // registered_type = TRUE;
753  }
754  if (safe_strcmp (param->param_type, QOF_TYPE_DOUBLE) == 0)
755  {
756  gdouble db;
757  gchar *tail;
758 
759  errno = 0;
760  db = strtod (value_string, &tail);
761  double_setter =
762  (void (*)(QofEntity *, gdouble)) param->param_setfcn;
763  if ((double_setter != NULL) && (errno == 0))
764  double_setter (ent, db);
765 // registered_type = TRUE;
766  }
767  if (safe_strcmp (param->param_type, QOF_TYPE_BOOLEAN) == 0)
768  {
769  gint val;
770  gboolean b;
771 
772  boolean_setter =
773  (void (*)(QofEntity *, gboolean)) param->param_setfcn;
774  val = qof_util_bool_to_int(value_string);
775  if ((val > 1) || (val < 0))
776  return FALSE;
777  b = (val == 1) ? TRUE : FALSE;
778  if (boolean_setter != NULL)
779  boolean_setter (ent, val);
780 // registered_type = TRUE;
781  }
782  if (safe_strcmp (param->param_type, QOF_TYPE_KVP) == 0)
783  {
784  /* unsupported */
785  return FALSE;
786 /* KvpFrame * frame;
787  KvpValue * value;
788 
789  kvp_frame_setter =
790  (void (*)(QofEntity *, KvpFrame *)) param->param_setfcn;
791  if (kvp_frame_setter != NULL)
792  kvp_frame_setter (rule->targetEnt, cm_kvp);
793 // registered_type = TRUE;*/
794  }
795  if (safe_strcmp (param->param_type, QOF_TYPE_CHAR) == 0)
796  {
797  char_setter =
798  (void (*)(QofEntity *, gchar)) param->param_setfcn;
799  if (char_setter != NULL)
800  char_setter (ent, value_string[0]);
801 // registered_type = TRUE;
802  }
803  if (safe_strcmp (param->param_type, QOF_TYPE_COLLECT) == 0)
804  {
805  /* unsupported */
806  return FALSE;
807  }
808  if (safe_strcmp (param->param_type, QOF_TYPE_CHOICE) == 0)
809  {
810  /* unsupported*/
811  return FALSE;
812  }
813 /* if (registered_type == FALSE)
814  {
815  referenceEnt =
816  cm_param->param_getfcn (rule->importEnt, cm_param);
817  if (referenceEnt)
818  {
819  reference_setter =
820  (void (*)(QofEntity *, QofEntity *)) cm_param->
821  param_setfcn;
822  if (reference_setter != NULL)
823  {
824  reference_setter (rule->targetEnt, referenceEnt);
825  }
826  }
827  }*/
828  return TRUE;
829 }
gchar* qof_util_param_to_string ( QofEntity ent,
const QofParam param 
)

Converts a parameter to a string for storage or display.

The returned string must be freed by the caller.

Use qof_util_param_set_string to set the parameter using the string. Designed for backends that store all values as strings.

< secondary collections are used for one-to-many references between entities and are implemented using QofCollection. These are NOT the same as the main collections in the QofBook. -# Each QofCollection contains one or many entities - all of a single type. -# The entity type within the collection can be determined at run time. -# Easy conversions to GList or whatever in the param_setfcn handler. -# Each parameter can have its own collection. -# Each entity can have a different type of collection to its siblings, provided that it is acceptable to the set function. -# Each object decides which types are acceptable for which parameter in the set functions. This is then part of the API for that object. QOF_TYPE_COLLECT has two functions, both related to one-to-many links: - Represent a reference between 2 entities with a list of acceptable types. (one object linked to many types of single entities) - Represent a reference between one entity and many entities of another type. (one object linked to many entities of a single type.) If the set function can handle it, it could also be used for true one-to-many links: one object linked to many entities of many types. n.b. Always subject to each collection holding only one type at runtime. (otherwise use books).

Definition at line 447 of file qofutil.c.

448 {
449  gchar *param_string;
450  gchar param_sa[GUID_ENCODING_LENGTH + 1];
451  gboolean known_type;
452  QofType paramType;
453  const GUID *param_guid;
454  QofNumeric param_numeric, (*numeric_getter) (QofEntity *, const QofParam *);
455  gdouble param_double, (*double_getter) (QofEntity *, const QofParam *);
456  gboolean param_boolean, (*boolean_getter) (QofEntity *, const QofParam *);
457  gint32 param_i32, (*int32_getter) (QofEntity *, const QofParam *);
458  gint64 param_i64, (*int64_getter) (QofEntity *, const QofParam *);
459  gchar param_char, (*char_getter) (QofEntity *, const QofParam *);
460 
461  param_string = NULL;
462  known_type = FALSE;
463  g_return_val_if_fail (ent && param, NULL);
464  paramType = param->param_type;
465  if (safe_strcmp (paramType, QOF_TYPE_STRING) == 0)
466  {
467  param_string = g_strdup (param->param_getfcn (ent, param));
468  if (param_string == NULL)
469  {
470  param_string = "";
471  }
472  known_type = TRUE;
473  return param_string;
474  }
475  if (safe_strcmp (paramType, QOF_TYPE_TIME) == 0)
476  {
477  QofTime *param_qt;
478  QofDate *qd;
479  param_qt = param->param_getfcn (ent, param);
480  qd = qof_date_from_qtime (param_qt);
481  return qof_date_print (qd, QOF_DATE_FORMAT_UTC);
482  }
483 #ifndef QOF_DISABLE_DEPRECATED
484  if (safe_strcmp (paramType, QOF_TYPE_DATE) == 0)
485  {
486  Timespec param_ts, (*date_getter) (QofEntity *, const QofParam *);
487  time_t param_t;
488  gchar param_date[MAX_DATE_LENGTH];
489 
490  date_getter =
491  (Timespec (*)(QofEntity *, const QofParam *)) param->param_getfcn;
492  param_ts = date_getter (ent, param);
493  param_t = param_ts.tv_sec;
494  strftime (param_date, MAX_DATE_LENGTH,
495  QOF_UTC_DATE_FORMAT, gmtime (&param_t));
496  param_string = g_strdup (param_date);
497  known_type = TRUE;
498  return param_string;
499  }
500 #endif
501  if ((safe_strcmp (paramType, QOF_TYPE_NUMERIC) == 0) ||
502  (safe_strcmp (paramType, QOF_TYPE_DEBCRED) == 0))
503  {
504  numeric_getter =
505  (QofNumeric (*)(QofEntity *, const QofParam *)) param->param_getfcn;
506  param_numeric = numeric_getter (ent, param);
507  param_string = g_strdup (qof_numeric_to_string (param_numeric));
508  known_type = TRUE;
509  return param_string;
510  }
511  if (safe_strcmp (paramType, QOF_TYPE_GUID) == 0)
512  {
513  param_guid = param->param_getfcn (ent, param);
514  guid_to_string_buff (param_guid, param_sa);
515  param_string = g_strdup (param_sa);
516  known_type = TRUE;
517  return param_string;
518  }
519  if (safe_strcmp (paramType, QOF_TYPE_INT32) == 0)
520  {
521  int32_getter =
522  (gint32 (*)(QofEntity *, const QofParam *)) param->param_getfcn;
523  param_i32 = int32_getter (ent, param);
524  param_string = g_strdup_printf ("%d", param_i32);
525  known_type = TRUE;
526  return param_string;
527  }
528  if (safe_strcmp (paramType, QOF_TYPE_INT64) == 0)
529  {
530  int64_getter =
531  (gint64 (*)(QofEntity *, const QofParam *)) param->param_getfcn;
532  param_i64 = int64_getter (ent, param);
533  param_string = g_strdup_printf ("%" G_GINT64_FORMAT, param_i64);
534  known_type = TRUE;
535  return param_string;
536  }
537  if (safe_strcmp (paramType, QOF_TYPE_DOUBLE) == 0)
538  {
539  double_getter =
540  (double (*)(QofEntity *, const QofParam *)) param->param_getfcn;
541  param_double = double_getter (ent, param);
542  param_string = g_strdup_printf ("%f", param_double);
543  known_type = TRUE;
544  return param_string;
545  }
546  if (safe_strcmp (paramType, QOF_TYPE_BOOLEAN) == 0)
547  {
548  boolean_getter =
549  (gboolean (*)(QofEntity *, const QofParam *)) param->param_getfcn;
550  param_boolean = boolean_getter (ent, param);
551  /* Boolean values need to be lowercase for QSF validation. */
552  if (param_boolean == TRUE)
553  {
554  param_string = g_strdup ("true");
555  }
556  else
557  {
558  param_string = g_strdup ("false");
559  }
560  known_type = TRUE;
561  return param_string;
562  }
563  /* "kvp" contains repeating values, cannot be a single string for the frame. */
564  if (safe_strcmp (paramType, QOF_TYPE_KVP) == 0)
565  {
566  KvpFrame *frame = NULL;
567  frame = param->param_getfcn (ent, param);
568  known_type = TRUE;
569  if (!kvp_frame_is_empty (frame))
570  {
571  GHashTable *hash = kvp_frame_get_hash (frame);
572  param_string = g_strdup_printf ("%s(%d)", QOF_TYPE_KVP,
573  g_hash_table_size (hash));
574  }
575  return param_string;
576  }
577  if (safe_strcmp (paramType, QOF_TYPE_CHAR) == 0)
578  {
579  char_getter =
580  (gchar (*)(QofEntity *, const QofParam *)) param->param_getfcn;
581  param_char = char_getter (ent, param);
582  known_type = TRUE;
583  return g_strdup_printf ("%c", param_char);
584  }
585  /* "collect" contains repeating values, cannot be a single string. */
586  if (safe_strcmp (paramType, QOF_TYPE_COLLECT) == 0)
587  {
588  QofCollection *col = NULL;
589  col = param->param_getfcn (ent, param);
590  known_type = TRUE;
591  return g_strdup_printf ("%s(%d)",
593  }
594  if (safe_strcmp (paramType, QOF_TYPE_CHOICE) == 0)
595  {
596  QofEntity *child = NULL;
597  child = param->param_getfcn (ent, param);
598  if (!child)
599  {
600  return param_string;
601  }
602  known_type = TRUE;
603  return g_strdup (qof_object_printable (child->e_type, child));
604  }
605  if (safe_strcmp (paramType, QOF_PARAM_BOOK) == 0)
606  {
607  QofBackend *be;
608  QofBook *book;
609  book = param->param_getfcn (ent, param);
610  PINFO (" book param %p", book);
611  be = qof_book_get_backend (book);
612  known_type = TRUE;
613  PINFO (" backend=%p", be);
614  if (!be)
615  {
616  return QOF_PARAM_BOOK;
617  }
618  param_string = g_strdup (be->fullpath);
619  PINFO (" fullpath=%s", param_string);
620  if (param_string)
621  {
622  return param_string;
623  }
624  param_guid = qof_entity_get_guid ((QofEntity*)book);
625  guid_to_string_buff (param_guid, param_sa);
626  PINFO (" book GUID=%s", param_sa);
627  param_string = g_strdup (param_sa);
628  return param_string;
629  }
630  if (!known_type)
631  {
632  QofEntity *child = NULL;
633  child = param->param_getfcn (ent, param);
634  if (!child)
635  {
636  return param_string;
637  }
638  return g_strdup (qof_object_printable (child->e_type, child));
639  }
640  return g_strdup ("");
641 }
void qof_util_string_cache_destroy ( void  )

The QOF String Cache:

Many strings used throughout QOF and QOF applications are likely to be duplicated.

QOF provides a reference counted cache system for the strings, which shares strings whenever possible.

Use qof_util_string_cache_insert to insert a string into the cache (it will return a pointer to the cached string). Basically you should use this instead of g_strdup.

Use qof_util_string_cache_remove (giving it a pointer to a cached string) if the string is unused. If this is the last reference to the string it will be removed from the cache, otherwise it will just decrement the reference count. Basically you should use this instead of g_free.

Just in case it's not clear: The remove function must NOT be called for the string you passed INTO the insert function. It must be called for the cached string that is returned by the insert function.

Note that all the work is done when inserting or removing. Once cached the strings are just plain C strings.

The string cache is demand-created on first use.Destroy the qof_util_string_cache

Definition at line 424 of file qofutil.c.

425 {
426  if (qof_string_cache)
427  g_cache_destroy (qof_string_cache);
428  qof_string_cache = NULL;
429 }
gpointer qof_util_string_cache_insert ( gconstpointer  key)

You can use this function with g_hash_table_insert(), for the key (or value), as long as you use the destroy notifier above.

Definition at line 439 of file qofutil.c.

440 {
441  if (key)
442  return g_cache_insert(qof_util_get_string_cache(), (gpointer)key);
443  return NULL;
444 }
void qof_util_string_cache_remove ( gconstpointer  key)

You can use this function as a destroy notifier for a GHashTable that uses common strings as keys (or values, for that matter.)

Definition at line 432 of file qofutil.c.

433 {
434  if (key)
435  g_cache_remove (qof_util_get_string_cache (), key);
436 }
gboolean qof_util_string_isnum ( const guchar *  s)

Returns true if string s is a number, possibly surrounded by whitespace.

Definition at line 195 of file qofutil.c.

196 {
197  if (s == NULL)
198  return FALSE;
199  if (*s == 0)
200  return FALSE;
201 
202  while (*s && isspace (*s))
203  s++;
204 
205  if (*s == 0)
206  return FALSE;
207  if (!isdigit (*s))
208  return FALSE;
209 
210  while (*s && isdigit (*s))
211  s++;
212 
213  if (*s == 0)
214  return TRUE;
215 
216  while (*s && isspace (*s))
217  s++;
218 
219  if (*s == 0)
220  return TRUE;
221 
222  return FALSE;
223 }
const gchar* qof_util_whitespace_filter ( const gchar *  val)

Return NULL if the field is whitespace (blank, tab, formfeed etc.) Else return pointer to first non-whitespace character.

Definition at line 231 of file qofutil.c.

232 {
233  size_t len;
234  if (!val)
235  return NULL;
236 
237  len = strspn (val, "\a\b\t\n\v\f\r ");
238  if (0 == val[len])
239  return NULL;
240  return val + len;
241 }
gint safe_strcasecmp ( const gchar *  da,
const gchar *  db 
)
case sensitive comparison of strings da and db - either

may be NULL. A non-NULL string is greater than a NULL string.

Parameters
dastring 1.
dbstring 2.
Returns
If da == NULL && db != NULL, returns -1. If da != NULL && db == NULL, returns +1. If da != NULL && db != NULL, returns the result of strcmp(da, db). If da == NULL && db == NULL, returns 0.

Definition at line 92 of file qofutil.c.

93 {
94  if ((da) && (db))
95  {
96  if ((da) != (db))
97  {
98  gint retval = strcasecmp ((da), (db));
99  /* if strings differ, return */
100  if (retval)
101  return retval;
102  }
103  }
104  else if ((!(da)) && (db))
105  return -1;
106  else if ((da) && (!(db)))
107  return +1;
108  return 0;
109 }
gint safe_strcmp ( const gchar *  da,
const gchar *  db 
)

The safe_strcmp compares strings da and db the same way that strcmp() does, except that either may be null. This routine assumes that a non-null string is always greater than a null string.

Parameters
dastring 1.
dbstring 2.
Returns
If da == NULL && db != NULL, returns -1. If da != NULL && db == NULL, returns +1. If da != NULL && db != NULL, returns the result of strcmp(da, db). If da == NULL && db == NULL, returns 0.

Definition at line 72 of file qofutil.c.

73 {
74  if ((da) && (db))
75  {
76  if ((da) != (db))
77  {
78  gint retval = strcmp ((da), (db));
79  /* if strings differ, return */
80  if (retval)
81  return retval;
82  }
83  }
84  else if ((!(da)) && (db))
85  return -1;
86  else if ((da) && (!(db)))
87  return +1;
88  return 0;
89 }
gchar* strncasestr ( const guchar *  str1,
const guchar *  str2,
size_t  len 
)

Search for str2 in first nchar chars of str1, ignore case. Return pointer to first match, or null. These are just like that strnstr and the strstr functions, except that they ignore the case.

Definition at line 45 of file qofutil.c.

46 {
47  while (*str1 && len--)
48  {
49  if (toupper (*str1) == toupper (*str2))
50  {
51  if (strncasecmp (str1, str2, strlen (str2)) == 0)
52  return (gchar *) str1;
53  }
54  str1++;
55  }
56  return NULL;
57 }
gchar* ultostr ( gulong  val,
gint  base 
)

The ultostr() subroutine is the inverse of strtoul(). It accepts a number and prints it in the indicated base. The returned string should be g_freed when done.

Definition at line 131 of file qofutil.c.

132 {
133  gchar buf[MAX_DIGITS];
134  gulong broke[MAX_DIGITS];
135  gint i;
136  gulong places = 0, reval;
137 
138  if ((2 > base) || (36 < base))
139  return NULL;
140 
141  /* count digits */
142  places = 0;
143  for (i = 0; i < MAX_DIGITS; i++)
144  {
145  broke[i] = val;
146  places++;
147  val /= base;
148  if (0 == val)
149  break;
150  }
151 
152  /* normalize */
153  reval = 0;
154  for (i = places - 2; i >= 0; i--)
155  {
156  reval += broke[i + 1];
157  reval *= base;
158  broke[i] -= reval;
159  }
160 
161  /* print */
162  for (i = 0; i < (gint) places; i++)
163  {
164  if (10 > broke[i])
165  {
166  buf[places - 1 - i] = 0x30 + broke[i]; /* ascii digit zero */
167  }
168  else
169  {
170  buf[places - 1 - i] = 0x41 - 10 + broke[i]; /* ascii capital A */
171  }
172  }
173  buf[places] = 0x0;
174 
175  return g_strdup (buf);
176 }