Branch data Line data Source code
1 : : /********************************************************************\
2 : : * qofutil.c -- QOF utility functions *
3 : : * Copyright (C) 1997 Robin D. Clark *
4 : : * Copyright (C) 1997-2001,2004 Linas Vepstas <linas@linas.org> *
5 : : * Copyright 2006 Neil Williams <linux@codehelp.co.uk> *
6 : : * *
7 : : * This program is free software; you can redistribute it and/or *
8 : : * modify it under the terms of the GNU General Public License as *
9 : : * published by the Free Software Foundation; either version 2 of *
10 : : * the License, or (at your option) any later version. *
11 : : * *
12 : : * This program is distributed in the hope that it will be useful, *
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 : : * GNU General Public License for more details. *
16 : : * *
17 : : * You should have received a copy of the GNU General Public License*
18 : : * along with this program; if not, contact: *
19 : : * *
20 : : * Free Software Foundation Voice: +1-617-542-5942 *
21 : : * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
22 : : * Boston, MA 02110-1301, USA gnu@gnu.org *
23 : : * *
24 : : * Author: Rob Clark (rclark@cs.hmc.edu) *
25 : : * Author: Linas Vepstas (linas@linas.org) *
26 : : \********************************************************************/
27 : :
28 : : #include <config.h>
29 : :
30 : : #include <ctype.h>
31 : : #include <glib.h>
32 : : #include <stdlib.h>
33 : : #include <string.h>
34 : : #include "qof.h"
35 : : #include "qof-backend.hpp"
36 : :
37 : : G_GNUC_UNUSED static QofLogModule log_module = QOF_MOD_UTIL;
38 : :
39 : : void
40 : 0 : g_hash_table_foreach_sorted(GHashTable *hash_table, GHFunc func, gpointer user_data, GCompareFunc compare_func)
41 : : {
42 : : GList *iter;
43 : 0 : GList *keys = g_list_sort(g_hash_table_get_keys(hash_table), compare_func);
44 : :
45 : 0 : for (iter = keys; iter; iter = iter->next)
46 : : {
47 : 0 : func(iter->data, g_hash_table_lookup(hash_table, iter->data), user_data);
48 : : }
49 : :
50 : 0 : g_list_free(keys);
51 : 0 : }
52 : :
53 : : gboolean
54 : 367 : qof_utf8_substr_nocase (const gchar *haystack, const gchar *needle)
55 : : {
56 : : gchar *haystack_casefold, *haystack_normalized;
57 : : gchar *needle_casefold, *needle_normalized;
58 : : gchar *p;
59 : :
60 : 367 : g_return_val_if_fail (haystack && needle, FALSE);
61 : :
62 : 367 : haystack_casefold = g_utf8_casefold (haystack, -1);
63 : 367 : haystack_normalized = g_utf8_normalize (haystack_casefold, -1,
64 : : G_NORMALIZE_NFC);
65 : 367 : g_free (haystack_casefold);
66 : :
67 : 367 : needle_casefold = g_utf8_casefold (needle, -1);
68 : 367 : needle_normalized = g_utf8_normalize (needle_casefold, -1, G_NORMALIZE_NFC);
69 : 367 : g_free (needle_casefold);
70 : :
71 : 367 : p = strstr (haystack_normalized, needle_normalized);
72 : 367 : g_free (haystack_normalized);
73 : 367 : g_free (needle_normalized);
74 : :
75 : 367 : return p != NULL;
76 : : }
77 : :
78 : : /** Use g_utf8_casefold and g_utf8_collate to compare two utf8 strings,
79 : : * ignore case. Return < 0 if da compares before db, 0 if they compare
80 : : * equal, > 0 if da compares after db. */
81 : : static gint
82 : 0 : qof_utf8_strcasecmp (const gchar *da, const gchar *db)
83 : : {
84 : : gchar *da_casefold, *db_casefold;
85 : : gint retval;
86 : :
87 : 0 : g_return_val_if_fail (da != NULL, 0);
88 : 0 : g_return_val_if_fail (db != NULL, 0);
89 : :
90 : 0 : da_casefold = g_utf8_casefold (da, -1);
91 : 0 : db_casefold = g_utf8_casefold (db, -1);
92 : 0 : retval = g_utf8_collate (da_casefold, db_casefold);
93 : 0 : g_free (da_casefold);
94 : 0 : g_free (db_casefold);
95 : :
96 : 0 : return retval;
97 : : }
98 : :
99 : : gint
100 : 0 : safe_strcasecmp (const gchar * da, const gchar * db)
101 : : {
102 : 0 : if ((da) && (db))
103 : : {
104 : 0 : if ((da) != (db))
105 : : {
106 : 0 : gint retval = qof_utf8_strcasecmp ((da), (db));
107 : : /* if strings differ, return */
108 : 0 : if (retval) return retval;
109 : : }
110 : 0 : }
111 : 0 : else if ((!(da)) && (db))
112 : : {
113 : 0 : return -1;
114 : : }
115 : 0 : else if ((da) && (!(db)))
116 : : {
117 : 0 : return +1;
118 : : }
119 : 0 : return 0;
120 : : }
121 : :
122 : : gint
123 : 18 : null_strcmp (const gchar * da, const gchar * db)
124 : : {
125 : 18 : if (da && db) return strcmp (da, db);
126 : 2 : if (!da && db && 0 == db[0]) return 0;
127 : 2 : if (!db && da && 0 == da[0]) return 0;
128 : 2 : if (!da && db) return -1;
129 : 2 : if (da && !db) return +1;
130 : 2 : return 0;
131 : : }
132 : :
133 : : #define MAX_DIGITS 50
134 : :
135 : : /* inverse of strtoul */
136 : : gchar *
137 : 0 : ultostr (gulong val, gint base)
138 : : {
139 : : gchar buf[MAX_DIGITS];
140 : : gulong broke[MAX_DIGITS];
141 : : gint i;
142 : 0 : gulong places = 0, reval;
143 : :
144 : 0 : if ((2 > base) || (36 < base)) return NULL;
145 : :
146 : : /* count digits */
147 : 0 : places = 0;
148 : 0 : for (i = 0; i < MAX_DIGITS; i++)
149 : : {
150 : 0 : broke[i] = val;
151 : 0 : places ++;
152 : 0 : val /= base;
153 : 0 : if (0 == val) break;
154 : : }
155 : :
156 : : /* normalize */
157 : 0 : reval = 0;
158 : 0 : for (i = places - 2; i >= 0; i--)
159 : : {
160 : 0 : reval += broke[i+1];
161 : 0 : reval *= base;
162 : 0 : broke[i] -= reval;
163 : : }
164 : :
165 : : /* print */
166 : 0 : for (i = 0; i < (gint)places; i++)
167 : : {
168 : 0 : if (10 > broke[i])
169 : : {
170 : 0 : buf[places-1-i] = 0x30 + broke[i]; /* ascii digit zero */
171 : : }
172 : : else
173 : : {
174 : 0 : buf[places-1-i] = 0x41 - 10 + broke[i]; /* ascii capital A */
175 : : }
176 : : }
177 : 0 : buf[places] = 0x0;
178 : :
179 : 0 : return g_strdup (buf);
180 : : }
181 : :
182 : : /* =================================================================== */
183 : : /* returns TRUE if the string is a number, possibly with whitespace */
184 : : /* =================================================================== */
185 : :
186 : : gboolean
187 : 0 : gnc_strisnum(const gchar *s)
188 : : {
189 : 0 : if (s == NULL) return FALSE;
190 : 0 : if (*s == 0) return FALSE;
191 : :
192 : 0 : while (*s && isspace(*s))
193 : 0 : s++;
194 : :
195 : 0 : if (*s == 0) return FALSE;
196 : 0 : if (!isdigit(*s)) return FALSE;
197 : :
198 : 0 : while (*s && isdigit(*s))
199 : 0 : s++;
200 : :
201 : 0 : if (*s == 0) return TRUE;
202 : :
203 : 0 : while (*s && isspace(*s))
204 : 0 : s++;
205 : :
206 : 0 : if (*s == 0) return TRUE;
207 : :
208 : 0 : return FALSE;
209 : : }
210 : :
211 : : /* =================================================================== */
212 : : /* Return NULL if the field is whitespace (blank, tab, formfeed etc.)
213 : : * Else return pointer to first non-whitespace character. */
214 : : /* =================================================================== */
215 : :
216 : : G_GNUC_UNUSED static const gchar *
217 : 0 : qof_util_whitespace_filter (const gchar * val)
218 : : {
219 : : size_t len;
220 : 0 : if (!val) return NULL;
221 : :
222 : 0 : len = strspn (val, "\a\b\t\n\v\f\r ");
223 : 0 : if (0 == val[len]) return NULL;
224 : 0 : return val + len;
225 : : }
226 : :
227 : : #ifdef THESE_CAN_BE_USEFUL_FOR_DEGUGGING
228 : : static guint g_str_hash_KEY(gconstpointer v)
229 : : {
230 : : return g_str_hash(v);
231 : : }
232 : : static guint g_str_hash_VAL(gconstpointer v)
233 : : {
234 : : return g_str_hash(v);
235 : : }
236 : : static gpointer g_strdup_VAL(gpointer v)
237 : : {
238 : : return g_strdup(v);
239 : : }
240 : : static gpointer g_strdup_KEY(gpointer v)
241 : : {
242 : : return g_strdup(v);
243 : : }
244 : : static void g_free_VAL(gpointer v)
245 : : {
246 : : return g_free(v);
247 : : }
248 : : static void g_free_KEY(gpointer v)
249 : : {
250 : : return g_free(v);
251 : : }
252 : : static gboolean qof_util_str_equal(gconstpointer v, gconstpointer v2)
253 : : {
254 : : return (v && v2) ? g_str_equal(v, v2) : FALSE;
255 : : }
256 : : #endif
257 : :
258 : : void
259 : 115 : qof_init (void)
260 : : {
261 : 115 : qof_log_init();
262 : 115 : qof_string_cache_init();
263 : 115 : qof_object_initialize ();
264 : 115 : qof_query_init ();
265 : 115 : qof_book_register ();
266 : 115 : }
267 : :
268 : : void
269 : 42 : qof_close(void)
270 : : {
271 : 42 : qof_query_shutdown ();
272 : 42 : qof_object_shutdown ();
273 : 42 : QofBackend::release_backends();
274 : 42 : qof_string_cache_destroy ();
275 : 42 : qof_log_shutdown();
276 : 42 : }
277 : :
278 : : /* ************************ END OF FILE ***************************** */
|