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 297 : 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 297 : g_return_val_if_fail (haystack && needle, FALSE);
61 :
62 297 : haystack_casefold = g_utf8_casefold (haystack, -1);
63 297 : haystack_normalized = g_utf8_normalize (haystack_casefold, -1,
64 : G_NORMALIZE_NFC);
65 297 : g_free (haystack_casefold);
66 :
67 297 : needle_casefold = g_utf8_casefold (needle, -1);
68 297 : needle_normalized = g_utf8_normalize (needle_casefold, -1, G_NORMALIZE_NFC);
69 297 : g_free (needle_casefold);
70 :
71 297 : p = strstr (haystack_normalized, needle_normalized);
72 297 : g_free (haystack_normalized);
73 297 : g_free (needle_normalized);
74 :
75 297 : 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 117 : qof_init (void)
260 : {
261 117 : qof_log_init();
262 117 : qof_string_cache_init();
263 117 : qof_object_initialize ();
264 117 : qof_query_init ();
265 117 : qof_book_register ();
266 117 : }
267 :
268 : void
269 43 : qof_close(void)
270 : {
271 43 : qof_query_shutdown ();
272 43 : qof_object_shutdown ();
273 43 : QofBackend::release_backends();
274 43 : qof_string_cache_destroy ();
275 43 : qof_log_shutdown();
276 43 : }
277 :
278 : /* ************************ END OF FILE ***************************** */
|