|
GnuCash 2.4.99
|
00001 /********************************************************************\ 00002 * qofutil.c -- QOF utility functions * 00003 * Copyright (C) 1997 Robin D. Clark * 00004 * Copyright (C) 1997-2001,2004 Linas Vepstas <linas@linas.org> * 00005 * Copyright 2006 Neil Williams <linux@codehelp.co.uk> * 00006 * * 00007 * This program is free software; you can redistribute it and/or * 00008 * modify it under the terms of the GNU General Public License as * 00009 * published by the Free Software Foundation; either version 2 of * 00010 * the License, or (at your option) any later version. * 00011 * * 00012 * This program is distributed in the hope that it will be useful, * 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00015 * GNU General Public License for more details. * 00016 * * 00017 * You should have received a copy of the GNU General Public License* 00018 * along with this program; if not, contact: * 00019 * * 00020 * Free Software Foundation Voice: +1-617-542-5942 * 00021 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * 00022 * Boston, MA 02110-1301, USA gnu@gnu.org * 00023 * * 00024 * Author: Rob Clark (rclark@cs.hmc.edu) * 00025 * Author: Linas Vepstas (linas@linas.org) * 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 #include "qofbackend-p.h" 00036 00037 static QofLogModule log_module = QOF_MOD_UTIL; 00038 00039 void 00040 g_hash_table_foreach_sorted(GHashTable *hash_table, GHFunc func, gpointer user_data, GCompareFunc compare_func) 00041 { 00042 GList *iter; 00043 GList *keys = g_list_sort(g_hash_table_get_keys(hash_table), compare_func); 00044 00045 for (iter = keys; iter; iter = iter->next) 00046 { 00047 func(iter->data, g_hash_table_lookup(hash_table, iter->data), user_data); 00048 } 00049 00050 g_list_free(keys); 00051 } 00052 00053 gboolean 00054 qof_utf8_substr_nocase (const gchar *haystack, const gchar *needle) 00055 { 00056 gchar *haystack_casefold, *haystack_normalized; 00057 gchar *needle_casefold, *needle_normalized; 00058 gchar *p; 00059 00060 g_return_val_if_fail (haystack && needle, FALSE); 00061 00062 haystack_casefold = g_utf8_casefold (haystack, -1); 00063 haystack_normalized = g_utf8_normalize (haystack_casefold, -1, 00064 G_NORMALIZE_ALL); 00065 g_free (haystack_casefold); 00066 00067 needle_casefold = g_utf8_casefold (needle, -1); 00068 needle_normalized = g_utf8_normalize (needle_casefold, -1, G_NORMALIZE_ALL); 00069 g_free (needle_casefold); 00070 00071 p = strstr (haystack_normalized, needle_normalized); 00072 g_free (haystack_normalized); 00073 g_free (needle_normalized); 00074 00075 return p != NULL; 00076 } 00077 00081 static gint 00082 qof_utf8_strcasecmp (const gchar *da, const gchar *db) 00083 { 00084 gchar *da_casefold, *db_casefold; 00085 gint retval; 00086 00087 g_return_val_if_fail (da != NULL, 0); 00088 g_return_val_if_fail (db != NULL, 0); 00089 00090 da_casefold = g_utf8_casefold (da, -1); 00091 db_casefold = g_utf8_casefold (db, -1); 00092 retval = g_utf8_collate (da_casefold, db_casefold); 00093 g_free (da_casefold); 00094 g_free (db_casefold); 00095 00096 return retval; 00097 } 00098 00099 gint 00100 safe_strcmp (const gchar * da, const gchar * db) 00101 { 00102 if ((da) && (db)) 00103 { 00104 if ((da) != (db)) 00105 { 00106 gint retval = strcmp ((da), (db)); 00107 /* if strings differ, return */ 00108 if (retval) return retval; 00109 } 00110 } 00111 else if ((!(da)) && (db)) 00112 { 00113 return -1; 00114 } 00115 else if ((da) && (!(db))) 00116 { 00117 return +1; 00118 } 00119 return 0; 00120 } 00121 00122 gint 00123 safe_strcasecmp (const gchar * da, const gchar * db) 00124 { 00125 if ((da) && (db)) 00126 { 00127 if ((da) != (db)) 00128 { 00129 gint retval = qof_utf8_strcasecmp ((da), (db)); 00130 /* if strings differ, return */ 00131 if (retval) return retval; 00132 } 00133 } 00134 else if ((!(da)) && (db)) 00135 { 00136 return -1; 00137 } 00138 else if ((da) && (!(db))) 00139 { 00140 return +1; 00141 } 00142 return 0; 00143 } 00144 00145 gint 00146 null_strcmp (const gchar * da, const gchar * db) 00147 { 00148 if (da && db) return strcmp (da, db); 00149 if (!da && db && 0 == db[0]) return 0; 00150 if (!db && da && 0 == da[0]) return 0; 00151 if (!da && db) return -1; 00152 if (da && !db) return +1; 00153 return 0; 00154 } 00155 00156 #define MAX_DIGITS 50 00157 00158 /* inverse of strtoul */ 00159 gchar * 00160 ultostr (gulong val, gint base) 00161 { 00162 gchar buf[MAX_DIGITS]; 00163 gulong broke[MAX_DIGITS]; 00164 gint i; 00165 gulong places = 0, reval; 00166 00167 if ((2 > base) || (36 < base)) return NULL; 00168 00169 /* count digits */ 00170 places = 0; 00171 for (i = 0; i < MAX_DIGITS; i++) 00172 { 00173 broke[i] = val; 00174 places ++; 00175 val /= base; 00176 if (0 == val) break; 00177 } 00178 00179 /* normalize */ 00180 reval = 0; 00181 for (i = places - 2; i >= 0; i--) 00182 { 00183 reval += broke[i+1]; 00184 reval *= base; 00185 broke[i] -= reval; 00186 } 00187 00188 /* print */ 00189 for (i = 0; i < (gint)places; i++) 00190 { 00191 if (10 > broke[i]) 00192 { 00193 buf[places-1-i] = 0x30 + broke[i]; /* ascii digit zero */ 00194 } 00195 else 00196 { 00197 buf[places-1-i] = 0x41 - 10 + broke[i]; /* ascii capital A */ 00198 } 00199 } 00200 buf[places] = 0x0; 00201 00202 return g_strdup (buf); 00203 } 00204 00205 /* =================================================================== */ 00206 /* returns TRUE if the string is a number, possibly with whitespace */ 00207 /* =================================================================== */ 00208 00209 gboolean 00210 gnc_strisnum(const gchar *s) 00211 { 00212 if (s == NULL) return FALSE; 00213 if (*s == 0) return FALSE; 00214 00215 while (*s && isspace(*s)) 00216 s++; 00217 00218 if (*s == 0) return FALSE; 00219 if (!isdigit(*s)) return FALSE; 00220 00221 while (*s && isdigit(*s)) 00222 s++; 00223 00224 if (*s == 0) return TRUE; 00225 00226 while (*s && isspace(*s)) 00227 s++; 00228 00229 if (*s == 0) return TRUE; 00230 00231 return FALSE; 00232 } 00233 00234 /* =================================================================== */ 00235 /* Return NULL if the field is whitespace (blank, tab, formfeed etc.) 00236 * Else return pointer to first non-whitespace character. */ 00237 /* =================================================================== */ 00238 00239 static const gchar * 00240 qof_util_whitespace_filter (const gchar * val) 00241 { 00242 size_t len; 00243 if (!val) return NULL; 00244 00245 len = strspn (val, "\a\b\t\n\v\f\r "); 00246 if (0 == val[len]) return NULL; 00247 return val + len; 00248 } 00249 00250 #ifdef THESE_CAN_BE_USEFUL_FOR_DEGUGGING 00251 static guint g_str_hash_KEY(gconstpointer v) 00252 { 00253 return g_str_hash(v); 00254 } 00255 static guint g_str_hash_VAL(gconstpointer v) 00256 { 00257 return g_str_hash(v); 00258 } 00259 static gpointer g_strdup_VAL(gpointer v) 00260 { 00261 return g_strdup(v); 00262 } 00263 static gpointer g_strdup_KEY(gpointer v) 00264 { 00265 return g_strdup(v); 00266 } 00267 static void g_free_VAL(gpointer v) 00268 { 00269 return g_free(v); 00270 } 00271 static void g_free_KEY(gpointer v) 00272 { 00273 return g_free(v); 00274 } 00275 static gboolean qof_util_str_equal(gconstpointer v, gconstpointer v2) 00276 { 00277 return (v && v2) ? g_str_equal(v, v2) : FALSE; 00278 } 00279 #endif 00280 00281 void 00282 qof_init (void) 00283 { 00284 g_type_init(); 00285 qof_log_init(); 00286 qof_string_cache_init(); 00287 guid_init (); 00288 qof_object_initialize (); 00289 qof_query_init (); 00290 qof_book_register (); 00291 } 00292 00293 void 00294 qof_close(void) 00295 { 00296 qof_query_shutdown (); 00297 qof_object_shutdown (); 00298 guid_shutdown (); 00299 qof_finalize_backend_libraries(); 00300 qof_string_cache_destroy (); 00301 qof_log_shutdown(); 00302 } 00303 00304 /* ************************ END OF FILE ***************************** */
1.7.4