qofutil.h

00001 /********************************************************************\
00002  * qof-util.h -- QOF utility functions                              *
00003  *                                                                  *
00004  * This program is free software; you can redistribute it and/or    *
00005  * modify it under the terms of the GNU General Public License as   *
00006  * published by the Free Software Foundation; either version 2 of   *
00007  * the License, or (at your option) any later version.              *
00008  *                                                                  *
00009  * This program is distributed in the hope that it will be useful,  *
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
00012  * GNU General Public License for more details.                     *
00013  *                                                                  *
00014  * You should have received a copy of the GNU General Public License*
00015  * along with this program; if not, contact:                        *
00016  *                                                                  *
00017  * Free Software Foundation           Voice:  +1-617-542-5942       *
00018  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
00019  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
00020 \********************************************************************/
00021 
00032 #ifndef QOF_UTIL_H
00033 #define QOF_UTIL_H
00034 
00035 #include <stddef.h>
00036 #include "qof.h"
00037 #include "qoflog.h"
00038 #include "qofutil.h"
00039 #include "qofbackend-p.h"
00040 #include "qofbook.h"
00041 #include "qofinstance.h"
00042 
00044 #if HAVE_SCANF_LLD
00045 # define QOF_SCANF_LLD "%lld"
00046 #else
00047 # define QOF_SCANF_LLD "%qd"
00048 #endif
00049 
00050 #define QOF_MOD_UTIL "qof-utilities"
00051 
00055 #define ENUM_BODY(name, value)           \
00056     name value,
00057 
00058 #define AS_STRING_CASE(name, value)      \
00059     case name: { return #name; }
00060 
00061 #define FROM_STRING_CASE(name, value)    \
00062     if (strcmp(str, #name) == 0) {       \
00063         return name;  }
00064 
00065 #define DEFINE_ENUM(name, list)          \
00066     typedef enum {                       \
00067         list(ENUM_BODY)                  \
00068     }name;
00069 
00070 #define AS_STRING_DEC(name, list)        \
00071     const gchar* name##asString(name n);
00072 
00073 #define AS_STRING_FUNC(name, list)        \
00074     const gchar* name##asString(name n) { \
00075         switch (n) {                      \
00076             list(AS_STRING_CASE)          \
00077             default: return "";  } }
00078 
00079 #define FROM_STRING_DEC(name, list)      \
00080     name name##fromString                \
00081     (const gchar* str);
00082 
00083 #define FROM_STRING_FUNC(name, list)     \
00084     name name##fromString                \
00085     (const gchar* str) {                 \
00086     if(str == NULL) { return 0; }        \
00087         list(FROM_STRING_CASE)           \
00088         return 0;  }
00089 
00105 #define DEFINE_ENUM_NON_TYPEDEF(name, list)   \
00106     enum name {                               \
00107         list(ENUM_BODY)                       \
00108     };
00109 
00110 #define FROM_STRING_DEC_NON_TYPEDEF(name, list)   \
00111    void name##fromString                          \
00112    (const gchar* str, enum name *type);
00113 
00114 #define FROM_STRING_CASE_NON_TYPEDEF(name, value) \
00115    if (strcmp(str, #name) == 0) { *type = name; }
00116 
00117 #define FROM_STRING_FUNC_NON_TYPEDEF(name, list)  \
00118    void name##fromString                          \
00119    (const gchar* str, enum name *type) {          \
00120    if(str == NULL) { return; }                    \
00121     list(FROM_STRING_CASE_NON_TYPEDEF) }
00122 
00123 #define AS_STRING_DEC_NON_TYPEDEF(name, list)     \
00124    const gchar* name##asString(enum name n);
00125 
00126 #define AS_STRING_FUNC_NON_TYPEDEF(name, list)    \
00127    const gchar* name##asString(enum name n) {     \
00128        switch (n) {                               \
00129            list(AS_STRING_CASE_NON_TYPEDEF)       \
00130            default: return ""; } }
00131 
00132 #define AS_STRING_CASE_NON_TYPEDEF(name, value)   \
00133    case name: { return #name; }
00134 
00146 void qof_init (void);
00147 
00154 void qof_close (void);
00155 
00158 /* **** Prototypes *********************************************/
00159 
00173 gint safe_strcmp (const gchar * da, const gchar * db);
00174 
00187 gint safe_strcasecmp (const gchar * da, const gchar * db);
00188 
00193 gint null_strcmp (const gchar * da, const gchar * db);
00194 
00198 extern gchar *strncasestr(const guchar *str1, const guchar *str2, 
00199         size_t len);
00200 
00201 extern gchar *strcasestr(const gchar *str1, const gchar *str2);
00202 
00206 gchar * ultostr (gulong val, gint base);
00207 
00210 gboolean gnc_strisnum(const guchar *s);
00211 
00212 #ifndef HAVE_STPCPY
00213 #define stpcpy g_stpcpy
00214 #endif
00215 
00219 const gchar * qof_util_whitespace_filter (const gchar * val);
00220 
00224 gint qof_util_bool_to_int (const gchar * val);
00225 
00230 gchar* qof_util_param_as_string(QofEntity *ent, QofParam *param);
00231 
00262 void qof_util_string_cache_destroy (void);
00263 
00267 void qof_util_string_cache_remove(gconstpointer key);
00268 
00272 gpointer qof_util_string_cache_insert(gconstpointer key);
00273 
00274 #define CACHE_INSERT(str) qof_util_string_cache_insert((gconstpointer)(str))
00275 #define CACHE_REMOVE(str) qof_util_string_cache_remove((str))
00276 
00277 /* Replace cached string currently in 'dst' with string in 'src'.
00278  * Typical usage:
00279  *     void foo_set_name(Foo *f, const char *str) {
00280  *        CACHE_REPLACE(f->name, str);
00281  *     }
00282  * It avoids unnecessary ejection by doing INSERT before REMOVE.
00283 */
00284 #define CACHE_REPLACE(dst, src) do {          \
00285         gpointer tmp = CACHE_INSERT((src));   \
00286         CACHE_REMOVE((dst));                  \
00287         (dst) = tmp;                          \
00288     } while (0)
00289 
00290 #define QOF_CACHE_NEW(void) qof_util_string_cache_insert("")
00291 
00302 #define QOF_BEGIN_EDIT(inst)                                        \
00303   if (!(inst)) return;                                              \
00304                                                                     \
00305   (inst)->editlevel++;                                              \
00306   if (1 < (inst)->editlevel) return;                                \
00307                                                                     \
00308   if (0 >= (inst)->editlevel)                                       \
00309   {                                                                 \
00310     PERR ("unbalanced call - resetting (was %d)", (inst)->editlevel); \
00311     (inst)->editlevel = 1;                                          \
00312   }                                                                 \
00313   ENTER ("(inst=%p)", (inst));                                      \
00314                                                                     \
00315   /* See if there's a backend.  If there is, invoke it. */          \
00316   {                                                                 \
00317     QofBackend * be;                                                \
00318     be = qof_book_get_backend ((inst)->book);                       \
00319       if (be && qof_backend_begin_exists(be)) {                     \
00320          qof_backend_run_begin(be, (inst));                         \
00321     } else {                                                        \
00322       /* We tried and failed to start transaction! */               \
00323       (inst)->dirty = TRUE;                                         \
00324     }                                                               \
00325   }                                                                 \
00326   LEAVE (" ");
00327 
00333 gboolean qof_begin_edit(QofInstance *inst);
00334 
00349 #define QOF_COMMIT_EDIT_PART1(inst) {                            \
00350   if (!(inst)) return;                                           \
00351                                                                  \
00352   (inst)->editlevel--;                                           \
00353   if (0 < (inst)->editlevel) return;                             \
00354                                                                  \
00355   /* The pricedb suffers from delayed update...     */          \
00356   /* This may be setting a bad precedent for other types, I fear. */ \
00357   /* Other types probably really should handle begin like this. */ \
00358   if ((-1 == (inst)->editlevel) && (inst)->dirty)                \
00359   {                                                              \
00360     QofBackend * be;                                             \
00361     be = qof_book_get_backend ((inst)->book);                    \
00362     if (be && qof_backend_begin_exists(be)) {                    \
00363       qof_backend_run_begin(be, (inst));                         \
00364     }                                                            \
00365     (inst)->editlevel = 0;                                       \
00366   }                                                              \
00367   if (0 > (inst)->editlevel)                                     \
00368   {                                                              \
00369     PERR ("unbalanced call - resetting (was %d)", (inst)->editlevel); \
00370     (inst)->editlevel = 0;                                       \
00371   }                                                              \
00372   ENTER ("(inst=%p) dirty=%d do-free=%d",                        \
00373             (inst), (inst)->dirty, (inst)->do_free);             \
00374 }
00375 
00381 gboolean qof_commit_edit(QofInstance *inst);
00382 
00402 gboolean
00403 qof_commit_edit_part2(QofInstance *inst, 
00404                       void (*on_error)(QofInstance *, QofBackendError), 
00405                       void (*on_done)(QofInstance *), 
00406                       void (*on_free)(QofInstance *));
00407 
00412 #define QOF_COMMIT_EDIT_PART2(inst,on_error,on_done,on_free) {   \
00413   QofBackend * be;                                               \
00414                                                                  \
00415   /* See if there's a backend.  If there is, invoke it. */       \
00416   be = qof_book_get_backend ((inst)->book);                      \
00417   if (be && qof_backend_commit_exists(be))                       \
00418   {                                                              \
00419     QofBackendError errcode;                                     \
00420                                                                  \
00421     /* clear errors */                                           \
00422     do {                                                         \
00423       errcode = qof_backend_get_error (be);                      \
00424     } while (ERR_BACKEND_NO_ERR != errcode);                     \
00425                                                                  \
00426     qof_backend_run_commit(be, (inst));                          \
00427     errcode = qof_backend_get_error (be);                        \
00428     if (ERR_BACKEND_NO_ERR != errcode)                           \
00429     {                                                            \
00430       /* XXX Should perform a rollback here */                   \
00431       (inst)->do_free = FALSE;                                   \
00432                                                                  \
00433       /* Push error back onto the stack */                       \
00434       qof_backend_set_error (be, errcode);                       \
00435       (on_error)((inst), errcode);                               \
00436     }                                                            \
00437     /* XXX the backend commit code should clear dirty!! */       \
00438     (inst)->dirty = FALSE;                                       \
00439   }                                                              \
00440   (on_done)(inst);                                               \
00441                                                                  \
00442   LEAVE ("inst=%p, dirty=%d do-free=%d",                         \
00443             (inst), (inst)->dirty, (inst)->do_free);             \
00444   if ((inst)->do_free) {                                         \
00445      (on_free)(inst);                                            \
00446      return;                                                     \
00447   }                                                              \
00448 }
00449     
00450 #endif /* QOF_UTIL_H */
00451 

Generated on Fri May 12 17:57:21 2006 for QOF by  doxygen 1.4.4