Utilities: Miscellany
[Query Object Framework]


Files

file  qofutil.h
 QOF utility functions.

Convenience wrappers

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

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; }

Defines

#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.
gboolean qof_util_param_set_string (QofEntity *ent, const QofParam *param, const gchar *value_string)
 Set a parameter from a value string.
gchar * qof_util_make_utf8 (gchar *string)
 Convert strings received from the wrapped objects into UTF-8.
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.
gboolean qof_util_param_commit (QofInstance *inst, const QofParam *param)
 Commit this parameter change, with undo support.


Define 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.

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 }

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 898 of file qofutil.c.

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 887 of file qofutil.c.

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.

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 }

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.

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 }

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:
inst The QofInstance.
param The parameter being modified.
Returns:
FALSE on error, otherwise TRUE.

Definition at line 306 of file qofutil.c.

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 }

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:
inst The QofInstance.
param The parameter being modified.
Returns:
FALSE on error, otherwise TRUE.

Definition at line 278 of file qofutil.c.

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 }

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:
ent The entity in which the value is to be set.
param The parameter that stores the value.
value_string A 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.

  1. Each QofCollection contains one or many entities - *all* of a single type.
  2. The entity type within the collection can be determined at run time.
  3. Easy conversions to GList or whatever in the param_setfcn handler.
  4. Each parameter can have its own collection.
  5. Each entity can have a different *type* of collection to its siblings, provided that it is acceptable to the set function.
  6. 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:

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 671 of file qofutil.c.

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 //      registered_type = TRUE;
00689     }
00690 #ifndef QOF_DISABLE_DEPRECATED
00691     if (safe_strcmp (param->param_type, QOF_TYPE_DATE) == 0)
00692     {
00693         return FALSE;
00694 //      registered_type = TRUE;
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 //      registered_type = TRUE;
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 //      registered_type = TRUE;
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 //      registered_type = TRUE;
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 //      registered_type = TRUE;
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 //      registered_type = TRUE;
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 //      registered_type = TRUE;
00781     }
00782     if (safe_strcmp (param->param_type, QOF_TYPE_KVP) == 0)
00783     {
00784         /* unsupported */
00785         return FALSE;
00786 /*      KvpFrame * frame;
00787         KvpValue * value;
00788 
00789         kvp_frame_setter =
00790             (void (*)(QofEntity *, KvpFrame *)) param->param_setfcn;
00791         if (kvp_frame_setter != NULL)
00792             kvp_frame_setter (rule->targetEnt, cm_kvp);
00793 //      registered_type = TRUE;*/
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 //      registered_type = TRUE;
00802     }
00803     if (safe_strcmp (param->param_type, QOF_TYPE_COLLECT) == 0)
00804     {
00805         /* unsupported */
00806         return FALSE;
00807     }
00808     if (safe_strcmp (param->param_type, QOF_TYPE_CHOICE) == 0)
00809     {
00810         /* unsupported*/
00811         return FALSE;
00812     }
00813 /*  if (registered_type == FALSE)
00814     {
00815         referenceEnt =
00816             cm_param->param_getfcn (rule->importEnt, cm_param);
00817         if (referenceEnt)
00818         {
00819             reference_setter =
00820                 (void (*)(QofEntity *, QofEntity *)) cm_param->
00821                 param_setfcn;
00822             if (reference_setter != NULL)
00823             {
00824                 reference_setter (rule->targetEnt, referenceEnt);
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 /* ************************ END OF FILE ***************************** */
00854 /* ************************ END OF FILE ***************************** */

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.

  1. Each QofCollection contains one or many entities - *all* of a single type.
  2. The entity type within the collection can be determined at run time.
  3. Easy conversions to GList or whatever in the param_setfcn handler.
  4. Each parameter can have its own collection.
  5. Each entity can have a different *type* of collection to its siblings, provided that it is acceptable to the set function.
  6. 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:

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.

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 (&param_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         /* Boolean values need to be lowercase for QSF validation. */
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     /* "kvp" contains repeating values, cannot be a single string for the frame. */
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     /* "collect" contains repeating values, cannot be a single string. */
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 /*  void (*kvp_frame_setter) (QofEntity *, KvpFrame *);
00657     void (*reference_setter) (QofEntity *, QofEntity *);
00658     void (*collection_setter) (QofEntity *, QofCollection *);*/
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;

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.

00425 {
00426     if (qof_string_cache)
00427         g_cache_destroy (qof_string_cache);
00428     qof_string_cache = NULL;
00429 }

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.

00440 {
00441     if (key)
00442         return g_cache_insert(qof_util_get_string_cache(), (gpointer)key);
00443     return NULL;
00444 }

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.

00433 {
00434     if (key)
00435         g_cache_remove (qof_util_get_string_cache (), key);
00436 }

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.

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 }

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.

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 }

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:
da string 1.
db string 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.

00093 {
00094     if ((da) && (db))
00095     {
00096         if ((da) != (db))
00097         {
00098             gint retval = strcasecmp ((da), (db));
00099             /* if strings differ, return */
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 }

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:
da string 1.
db string 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.

00073 {
00074     if ((da) && (db))
00075     {
00076         if ((da) != (db))
00077         {
00078             gint retval = strcmp ((da), (db));
00079             /* if strings differ, return */
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 }

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.

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 }

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.

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     /* count digits */
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     /* normalize */
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     /* print */
00162     for (i = 0; i < (gint) places; i++)
00163     {
00164         if (10 > broke[i])
00165         {
00166             buf[places - 1 - i] = 0x30 + broke[i];  /* ascii digit zero */
00167         }
00168         else
00169         {
00170             buf[places - 1 - i] = 0x41 - 10 + broke[i]; /* ascii capital A */
00171         }
00172     }
00173     buf[places] = 0x0;
00174 
00175     return g_strdup (buf);
00176 }


Generated on Thu Jan 31 22:50:27 2008 for QOF by  doxygen 1.5.4