Branch data Line data Source code
1 : : /********************************************************************\
2 : : * QueryCore.c -- API for providing core Query data types *
3 : : * Copyright (C) 2002 Derek Atkins <warlord@MIT.EDU> *
4 : : * *
5 : : * This program is free software; you can redistribute it and/or *
6 : : * modify it under the terms of the GNU General Public License as *
7 : : * published by the Free Software Foundation; either version 2 of *
8 : : * the License, or (at your option) any later version. *
9 : : * *
10 : : * This program is distributed in the hope that it will be useful, *
11 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 : : * GNU General Public License for more details. *
14 : : * *
15 : : * You should have received a copy of the GNU General Public License*
16 : : * along with this program; if not, contact: *
17 : : * *
18 : : * Free Software Foundation Voice: +1-617-542-5942 *
19 : : * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
20 : : * Boston, MA 02110-1301, USA gnu@gnu.org *
21 : : * *
22 : : \********************************************************************/
23 : :
24 : : #include "guid.hpp"
25 : : #include <config.h>
26 : :
27 : : #include <glib.h>
28 : : #include <stdlib.h>
29 : :
30 : : #include "qof.h"
31 : : #include "qofquerycore-p.h"
32 : :
33 : : static QofLogModule log_module = QOF_MOD_QUERY;
34 : :
35 : : /* A function to destroy a query predicate's pdata */
36 : : typedef void (*QueryPredDataFree) (QofQueryPredData *pdata);
37 : :
38 : : /* A function to copy a query's predicate data */
39 : : typedef QofQueryPredData *(*QueryPredicateCopyFunc) (const QofQueryPredData *pdata);
40 : :
41 : : /* A function to take the object, apply the getter->param_getfcn,
42 : : * and return a printable string. Note that this QofParam->getfnc
43 : : * function should be returning a type equal to this core object type.
44 : : *
45 : : * Note that this string MUST be freed by the caller.
46 : : */
47 : : typedef char * (*QueryToString) (gpointer object, QofParam *getter);
48 : :
49 : : /* A function to test for equality of predicate data */
50 : : typedef gboolean (*QueryPredicateEqual) (const QofQueryPredData *p1,
51 : : const QofQueryPredData *p2);
52 : :
53 : : static QueryPredicateCopyFunc qof_query_copy_predicate (QofType type);
54 : : static QueryPredDataFree qof_query_predicate_free (QofType type);
55 : :
56 : : /* Core Type Predicate helpers */
57 : : typedef const char * (*query_string_getter) (gpointer, QofParam *);
58 : : static const char * query_string_type = QOF_TYPE_STRING;
59 : :
60 : : typedef time64 (*query_date_getter) (gpointer, QofParam *);
61 : : static const char * query_date_type = QOF_TYPE_DATE;
62 : :
63 : : typedef gnc_numeric (*query_numeric_getter) (gpointer, QofParam *);
64 : : static const char * query_numeric_type = QOF_TYPE_NUMERIC;
65 : :
66 : : typedef GList * (*query_glist_getter) (gpointer, QofParam *);
67 : : typedef const GncGUID * (*query_guid_getter) (gpointer, QofParam *);
68 : : static const char * query_guid_type = QOF_TYPE_GUID;
69 : :
70 : : typedef gint32 (*query_int32_getter) (gpointer, QofParam *);
71 : : static const char * query_int32_type = QOF_TYPE_INT32;
72 : :
73 : : typedef gint64 (*query_int64_getter) (gpointer, QofParam *);
74 : : static const char * query_int64_type = QOF_TYPE_INT64;
75 : :
76 : : typedef double (*query_double_getter) (gpointer, QofParam *);
77 : : static const char * query_double_type = QOF_TYPE_DOUBLE;
78 : :
79 : : typedef gboolean (*query_boolean_getter) (gpointer, QofParam *);
80 : : static const char * query_boolean_type = QOF_TYPE_BOOLEAN;
81 : :
82 : : typedef char (*query_char_getter) (gpointer, QofParam *);
83 : : static const char * query_char_type = QOF_TYPE_CHAR;
84 : :
85 : : typedef QofCollection * (*query_collect_getter) (gpointer, QofParam*);
86 : : static const char * query_collect_type = QOF_TYPE_COLLECT;
87 : :
88 : : typedef const GncGUID * (*query_choice_getter) (gpointer, QofParam *);
89 : : static const char * query_choice_type = QOF_TYPE_CHOICE;
90 : :
91 : : /* Tables for predicate storage and lookup */
92 : : static gboolean initialized = FALSE;
93 : : static GHashTable *predTable = nullptr;
94 : : static GHashTable *cmpTable = nullptr;
95 : : static GHashTable *copyTable = nullptr;
96 : : static GHashTable *freeTable = nullptr;
97 : : static GHashTable *toStringTable = nullptr;
98 : : static GHashTable *predEqualTable = nullptr;
99 : :
100 : : #define COMPARE_ERROR -3
101 : : #define PREDICATE_ERROR -2
102 : :
103 : : #define VERIFY_PDATA(str) { \
104 : : g_return_if_fail (pd != nullptr); \
105 : : g_return_if_fail (pd->type_name == str || \
106 : : !g_strcmp0 (str, pd->type_name)); \
107 : : }
108 : : #define VERIFY_PDATA_R(str) { \
109 : : g_return_val_if_fail (pd != nullptr, nullptr); \
110 : : g_return_val_if_fail (pd->type_name == str || \
111 : : !g_strcmp0 (str, pd->type_name), \
112 : : nullptr); \
113 : : }
114 : : #define VERIFY_PREDICATE(str) { \
115 : : g_return_val_if_fail (getter != nullptr, PREDICATE_ERROR); \
116 : : g_return_val_if_fail (getter->param_getfcn != nullptr, PREDICATE_ERROR); \
117 : : g_return_val_if_fail (pd != nullptr, PREDICATE_ERROR); \
118 : : g_return_val_if_fail (pd->type_name == str || \
119 : : !g_strcmp0 (str, pd->type_name), \
120 : : PREDICATE_ERROR); \
121 : : }
122 : :
123 : : /* *******************************************************************/
124 : : /* TYPE-HANDLING FUNCTIONS */
125 : :
126 : : /* QOF_TYPE_STRING */
127 : :
128 : : static int
129 : 3462 : string_match_predicate (gpointer object,
130 : : QofParam *getter,
131 : : QofQueryPredData *pd)
132 : : {
133 : 3462 : query_string_t pdata = (query_string_t) pd;
134 : : const char *s;
135 : 3462 : int ret = 0;
136 : :
137 : 3462 : VERIFY_PREDICATE (query_string_type);
138 : :
139 : 3462 : s = ((query_string_getter)getter->param_getfcn) (object, getter);
140 : :
141 : 3462 : if (!s) s = "";
142 : :
143 : 3462 : if (pdata->is_regex)
144 : : {
145 : : regmatch_t match;
146 : 95 : if (!regexec (&pdata->compiled, s, 1, &match, 0))
147 : 0 : ret = 1;
148 : : }
149 : : else
150 : : {
151 : 3367 : if (pdata->options == QOF_STRING_MATCH_CASEINSENSITIVE)
152 : : {
153 : 367 : if (pd->how == QOF_COMPARE_CONTAINS || pd->how == QOF_COMPARE_NCONTAINS)
154 : : {
155 : 387 : if (qof_utf8_substr_nocase (s, pdata->matchstring)) //uses strstr
156 : 20 : ret = 1;
157 : : }
158 : : else
159 : : {
160 : 0 : if (safe_strcasecmp (s, pdata->matchstring) == 0) //uses collate
161 : 0 : ret = 1;
162 : : }
163 : : }
164 : : else
165 : : {
166 : 3000 : if (pd->how == QOF_COMPARE_CONTAINS || pd->how == QOF_COMPARE_NCONTAINS)
167 : : {
168 : 3880 : if (strstr (s, pdata->matchstring))
169 : 880 : ret = 1;
170 : : }
171 : : else
172 : : {
173 : 0 : if (g_strcmp0 (s, pdata->matchstring) == 0)
174 : 0 : ret = 1;
175 : : }
176 : : }
177 : : }
178 : :
179 : 3462 : switch (pd->how)
180 : : {
181 : 3462 : case QOF_COMPARE_CONTAINS:
182 : 3462 : return ret;
183 : 0 : case QOF_COMPARE_NCONTAINS:
184 : 0 : return !ret;
185 : 0 : case QOF_COMPARE_EQUAL:
186 : 0 : return ret;
187 : 0 : case QOF_COMPARE_NEQ:
188 : 0 : return !ret;
189 : 0 : default:
190 : 0 : PWARN ("bad match type: %d", pd->how);
191 : 0 : return 0;
192 : : }
193 : : }
194 : :
195 : : static int
196 : 68 : string_compare_func (gpointer a, gpointer b, gint options,
197 : : QofParam *getter)
198 : : {
199 : : const char *s1, *s2;
200 : 68 : g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
201 : :
202 : 68 : s1 = ((query_string_getter)getter->param_getfcn) (a, getter);
203 : 68 : s2 = ((query_string_getter)getter->param_getfcn) (b, getter);
204 : :
205 : 68 : if (options == QOF_STRING_MATCH_CASEINSENSITIVE)
206 : 0 : return safe_strcasecmp (s1, s2);
207 : :
208 : 68 : return g_strcmp0 (s1, s2);
209 : : }
210 : :
211 : : int
212 : 8 : qof_string_number_compare_func (gpointer a, gpointer b, gint options,
213 : : QofParam *getter)
214 : : {
215 : : const char *s1, *s2;
216 : : char *sr1, *sr2;
217 : : long i1, i2;
218 : 8 : g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
219 : :
220 : 8 : s1 = ((query_string_getter)getter->param_getfcn) (a, getter);
221 : 8 : s2 = ((query_string_getter)getter->param_getfcn) (b, getter);
222 : :
223 : : // Deal with nullptr strings
224 : 8 : if (s1 == s2) return 0;
225 : 8 : if (!s1 && s2) return -1;
226 : 8 : if (s1 && !s2) return 1;
227 : :
228 : : // Convert to integers and test
229 : 8 : i1 = strtol(s1, &sr1, 10);
230 : 8 : i2 = strtol(s2, &sr2, 10);
231 : 8 : if (i1 < i2) return -1;
232 : 8 : if (i1 > i2) return 1;
233 : :
234 : : // If the integers match, then test the REST of the string as text.
235 : 8 : if (options == QOF_STRING_MATCH_CASEINSENSITIVE)
236 : 0 : return safe_strcasecmp (sr1, sr2);
237 : :
238 : 8 : return g_strcmp0 (sr1, sr2);
239 : : }
240 : :
241 : : static void
242 : 13675 : string_free_pdata (QofQueryPredData *pd)
243 : : {
244 : 13675 : query_string_t pdata = (query_string_t) pd;
245 : :
246 : 13675 : VERIFY_PDATA (query_string_type);
247 : :
248 : 13675 : if (pdata->is_regex)
249 : 800 : regfree (&pdata->compiled);
250 : :
251 : 13675 : g_free (pdata->matchstring);
252 : 13675 : g_free (pdata);
253 : : }
254 : :
255 : : static QofQueryPredData *
256 : 12297 : string_copy_predicate (const QofQueryPredData *pd)
257 : : {
258 : 12297 : const query_string_t pdata = (const query_string_t) pd;
259 : :
260 : 12297 : VERIFY_PDATA_R (query_string_type);
261 : :
262 : 12297 : return qof_query_string_predicate (pd->how, pdata->matchstring,
263 : : pdata->options,
264 : 12297 : pdata->is_regex);
265 : : }
266 : :
267 : : static gboolean
268 : 233 : string_predicate_equal (const QofQueryPredData *p1, const QofQueryPredData *p2)
269 : : {
270 : 233 : const query_string_t pd1 = (const query_string_t) p1;
271 : 233 : const query_string_t pd2 = (const query_string_t) p2;
272 : :
273 : 233 : if (pd1->options != pd2->options) return FALSE;
274 : 233 : if (pd1->is_regex != pd2->is_regex) return FALSE;
275 : 233 : return (g_strcmp0 (pd1->matchstring, pd2->matchstring) == 0);
276 : : }
277 : :
278 : : QofQueryPredData *
279 : 14094 : qof_query_string_predicate (QofQueryCompare how,
280 : : const char *str, QofStringMatch options,
281 : : gboolean is_regex)
282 : : {
283 : : query_string_t pdata;
284 : :
285 : 14094 : g_return_val_if_fail (str, nullptr);
286 : : // g_return_val_if_fail (*str != '\0', nullptr);
287 : 14094 : g_return_val_if_fail (how == QOF_COMPARE_CONTAINS || how == QOF_COMPARE_NCONTAINS ||
288 : : how == QOF_COMPARE_EQUAL || how == QOF_COMPARE_NEQ, nullptr);
289 : :
290 : 13734 : pdata = g_new0 (query_string_def, 1);
291 : 13734 : pdata->pd.type_name = query_string_type;
292 : 13734 : pdata->pd.how = how;
293 : 13734 : pdata->options = options;
294 : 13734 : pdata->matchstring = g_strdup (str);
295 : :
296 : 13734 : if (is_regex)
297 : : {
298 : : int rc;
299 : 859 : int flags = REG_EXTENDED;
300 : 859 : if (options == QOF_STRING_MATCH_CASEINSENSITIVE)
301 : 345 : flags |= REG_ICASE;
302 : :
303 : 859 : rc = regcomp(&pdata->compiled, str, flags);
304 : 859 : if (rc)
305 : : {
306 : 59 : g_free(pdata->matchstring);
307 : 59 : g_free(pdata);
308 : 59 : return nullptr;
309 : : }
310 : 800 : pdata->is_regex = TRUE;
311 : : }
312 : :
313 : 13675 : return ((QofQueryPredData*)pdata);
314 : : }
315 : :
316 : : static char *
317 : 0 : string_to_string (gpointer object, QofParam *getter)
318 : : {
319 : : const char *res;
320 : 0 : res = ((query_string_getter)getter->param_getfcn)(object, getter);
321 : 0 : if (res)
322 : 0 : return g_strdup (res);
323 : 0 : return nullptr;
324 : : }
325 : :
326 : : /* QOF_TYPE_DATE =================================================== */
327 : :
328 : : static int
329 : 165804 : date_compare (time64 ta, time64 tb, QofDateMatch options)
330 : : {
331 : :
332 : 165804 : if (options == QOF_DATE_MATCH_DAY)
333 : : {
334 : 0 : ta = time64CanonicalDayTime (ta);
335 : 0 : tb = time64CanonicalDayTime (tb);
336 : : }
337 : :
338 : 165804 : if (ta < tb)
339 : 23275 : return -1;
340 : 142529 : if (ta > tb)
341 : 141829 : return 1;
342 : :
343 : 700 : return 0;
344 : : }
345 : :
346 : : static int
347 : 162590 : date_match_predicate (gpointer object, QofParam *getter,
348 : : QofQueryPredData *pd)
349 : : {
350 : 162590 : query_date_t pdata = (query_date_t)pd;
351 : : time64 objtime;
352 : : int compare;
353 : :
354 : 162590 : VERIFY_PREDICATE (query_date_type);
355 : :
356 : 162590 : objtime = ((query_date_getter)getter->param_getfcn) (object, getter);
357 : 162590 : compare = date_compare (objtime, pdata->date, pdata->options);
358 : :
359 : 162590 : switch (pd->how)
360 : : {
361 : 0 : case QOF_COMPARE_LT:
362 : 0 : return (compare < 0);
363 : 78533 : case QOF_COMPARE_LTE:
364 : 78533 : return (compare <= 0);
365 : 0 : case QOF_COMPARE_EQUAL:
366 : 0 : return (compare == 0);
367 : 0 : case QOF_COMPARE_GT:
368 : 0 : return (compare > 0);
369 : 84057 : case QOF_COMPARE_GTE:
370 : 84057 : return (compare >= 0);
371 : 0 : case QOF_COMPARE_NEQ:
372 : 0 : return (compare != 0);
373 : 0 : default:
374 : 0 : PWARN ("bad match type: %d", pd->how);
375 : 0 : return 0;
376 : : }
377 : : }
378 : :
379 : : static int
380 : 3214 : date_compare_func (gpointer a, gpointer b, gint options, QofParam *getter)
381 : : {
382 : : time64 ta, tb;
383 : :
384 : 3214 : g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
385 : :
386 : 3214 : ta = ((query_date_getter)getter->param_getfcn) (a, getter);
387 : 3214 : tb = ((query_date_getter)getter->param_getfcn) (b, getter);
388 : :
389 : 3214 : return date_compare (ta, tb, static_cast<QofDateMatch>(options));
390 : : }
391 : :
392 : : static void
393 : 18973 : date_free_pdata (QofQueryPredData *pd)
394 : : {
395 : 18973 : query_date_t pdata = (query_date_t)pd;
396 : :
397 : 18973 : VERIFY_PDATA (query_date_type);
398 : :
399 : 18973 : g_free (pdata);
400 : : }
401 : :
402 : : static QofQueryPredData *
403 : 14915 : date_copy_predicate (const QofQueryPredData *pd)
404 : : {
405 : 14915 : const query_date_t pdata = (const query_date_t)pd;
406 : :
407 : 14915 : VERIFY_PDATA_R (query_date_type);
408 : :
409 : 14915 : return qof_query_date_predicate (pd->how, pdata->options, pdata->date);
410 : : }
411 : :
412 : : static gboolean
413 : 241 : date_predicate_equal (const QofQueryPredData *p1, const QofQueryPredData *p2)
414 : : {
415 : 241 : const query_date_t pd1 = (const query_date_t) p1;
416 : 241 : const query_date_t pd2 = (const query_date_t) p2;
417 : :
418 : 241 : if (pd1->options != pd2->options) return FALSE;
419 : 241 : return (pd1->date == pd2->date);
420 : : }
421 : :
422 : : QofQueryPredData *
423 : 18973 : qof_query_date_predicate (QofQueryCompare how,
424 : : QofDateMatch options, time64 date)
425 : : {
426 : : query_date_t pdata;
427 : :
428 : 18973 : pdata = g_new0 (query_date_def, 1);
429 : 18973 : pdata->pd.type_name = query_date_type;
430 : 18973 : pdata->pd.how = how;
431 : 18973 : pdata->options = options;
432 : 18973 : pdata->date = date;
433 : 18973 : return ((QofQueryPredData*)pdata);
434 : : }
435 : :
436 : : gboolean
437 : 2 : qof_query_date_predicate_get_date (const QofQueryPredData *pd, time64 *date)
438 : : {
439 : 2 : const query_date_t pdata = (const query_date_t)pd;
440 : :
441 : 2 : if (pdata->pd.type_name != query_date_type)
442 : 1 : return FALSE;
443 : 1 : *date = pdata->date;
444 : 1 : return TRUE;
445 : : }
446 : :
447 : : static char *
448 : 0 : date_to_string (gpointer object, QofParam *getter)
449 : : {
450 : 0 : time64 tt = ((query_date_getter)getter->param_getfcn)(object, getter);
451 : :
452 : 0 : if (tt != INT64_MAX)
453 : 0 : return qof_print_date (tt);
454 : :
455 : 0 : return nullptr;
456 : : }
457 : :
458 : : /* QOF_TYPE_NUMERIC ================================================= */
459 : :
460 : : static int
461 : 601 : numeric_match_predicate (gpointer object, QofParam *getter,
462 : : QofQueryPredData* pd)
463 : : {
464 : 601 : query_numeric_t pdata = (query_numeric_t)pd;
465 : : gnc_numeric obj_val;
466 : : int compare;
467 : :
468 : 601 : VERIFY_PREDICATE (query_numeric_type);
469 : :
470 : 601 : obj_val = ((query_numeric_getter)getter->param_getfcn) (object, getter);
471 : :
472 : 601 : switch (pdata->options)
473 : : {
474 : 0 : case QOF_NUMERIC_MATCH_CREDIT:
475 : 0 : if (gnc_numeric_positive_p (obj_val)) return 0;
476 : 0 : break;
477 : 0 : case QOF_NUMERIC_MATCH_DEBIT:
478 : 0 : if (gnc_numeric_negative_p (obj_val)) return 0;
479 : 0 : break;
480 : 601 : default:
481 : 601 : break;
482 : : }
483 : :
484 : : /* Amounts are considered to be 'equal' if they match to
485 : : * four decimal places. (epsilon=1/10000) */
486 : 601 : if (pd->how == QOF_COMPARE_EQUAL || pd->how == QOF_COMPARE_NEQ)
487 : : {
488 : 601 : gnc_numeric cmp_val = gnc_numeric_create (1, 10000);
489 : 601 : compare =
490 : 601 : (gnc_numeric_compare (gnc_numeric_abs
491 : : (gnc_numeric_sub (gnc_numeric_abs (obj_val),
492 : : gnc_numeric_abs (pdata->amount),
493 : : 100000, GNC_HOW_RND_ROUND_HALF_UP)),
494 : 601 : cmp_val) < 0);
495 : 601 : }
496 : : else
497 : 0 : compare = gnc_numeric_compare (gnc_numeric_abs (obj_val), pdata->amount);
498 : :
499 : 601 : switch (pd->how)
500 : : {
501 : 0 : case QOF_COMPARE_LT:
502 : 0 : return (compare < 0);
503 : 0 : case QOF_COMPARE_LTE:
504 : 0 : return (compare <= 0);
505 : 601 : case QOF_COMPARE_EQUAL:
506 : 601 : return compare;
507 : 0 : case QOF_COMPARE_GT:
508 : 0 : return (compare > 0);
509 : 0 : case QOF_COMPARE_GTE:
510 : 0 : return (compare >= 0);
511 : 0 : case QOF_COMPARE_NEQ:
512 : 0 : return !compare;
513 : 0 : default:
514 : 0 : PWARN ("bad match type: %d", pd->how);
515 : 0 : return 0;
516 : : }
517 : : }
518 : :
519 : : static int
520 : 477 : numeric_compare_func (gpointer a, gpointer b, gint options, QofParam *getter)
521 : : {
522 : : gnc_numeric va, vb;
523 : :
524 : 477 : g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
525 : :
526 : 477 : va = ((query_numeric_getter)getter->param_getfcn) (a, getter);
527 : 477 : vb = ((query_numeric_getter)getter->param_getfcn) (b, getter);
528 : :
529 : 477 : return gnc_numeric_compare (va, vb);
530 : : }
531 : :
532 : : static void
533 : 12985 : numeric_free_pdata (QofQueryPredData* pd)
534 : : {
535 : 12985 : query_numeric_t pdata = (query_numeric_t)pd;
536 : 12985 : VERIFY_PDATA (query_numeric_type);
537 : 12985 : g_free (pdata);
538 : : }
539 : :
540 : : static QofQueryPredData *
541 : 10985 : numeric_copy_predicate (const QofQueryPredData *pd)
542 : : {
543 : 10985 : const query_numeric_t pdata = (const query_numeric_t)pd;
544 : 10985 : VERIFY_PDATA_R (query_numeric_type);
545 : 10985 : return qof_query_numeric_predicate (pd->how, pdata->options, pdata->amount);
546 : : }
547 : :
548 : : static gboolean
549 : 729 : numeric_predicate_equal (const QofQueryPredData *p1, const QofQueryPredData *p2)
550 : : {
551 : 729 : const query_numeric_t pd1 = (const query_numeric_t) p1;
552 : 729 : const query_numeric_t pd2 = (const query_numeric_t) p2;
553 : :
554 : 729 : if (pd1->options != pd2->options) return FALSE;
555 : 729 : return gnc_numeric_equal (pd1->amount, pd2->amount);
556 : : }
557 : :
558 : : QofQueryPredData *
559 : 12985 : qof_query_numeric_predicate (QofQueryCompare how,
560 : : QofNumericMatch options,
561 : : gnc_numeric value)
562 : : {
563 : : query_numeric_t pdata;
564 : 12985 : pdata = g_new0 (query_numeric_def, 1);
565 : 12985 : pdata->pd.type_name = query_numeric_type;
566 : 12985 : pdata->pd.how = how;
567 : 12985 : pdata->options = options;
568 : 12985 : pdata->amount = value;
569 : 12985 : return ((QofQueryPredData*)pdata);
570 : : }
571 : :
572 : : static char *
573 : 0 : numeric_to_string (gpointer object, QofParam *getter)
574 : : {
575 : : gnc_numeric num;
576 : 0 : num = ((query_numeric_getter)getter->param_getfcn)(object, getter);
577 : :
578 : 0 : return gnc_numeric_to_string (num);
579 : : }
580 : :
581 : : static char *
582 : 0 : debcred_to_string (gpointer object, QofParam *getter)
583 : : {
584 : : gnc_numeric num;
585 : 0 : num = ((query_numeric_getter)getter->param_getfcn)(object, getter);
586 : :
587 : 0 : return gnc_numeric_to_string (num);
588 : : }
589 : :
590 : : /* QOF_TYPE_GUID =================================================== */
591 : :
592 : : static int
593 : 535579 : guid_match_predicate (gpointer object, QofParam *getter,
594 : : QofQueryPredData *pd)
595 : : {
596 : 535579 : query_guid_t pdata = (query_guid_t)pd;
597 : : GList *node, *o_list;
598 : 535579 : const GncGUID *guid = nullptr;
599 : :
600 : 535579 : VERIFY_PREDICATE (query_guid_type);
601 : :
602 : 535579 : switch (pdata->options)
603 : : {
604 : :
605 : 200 : case QOF_GUID_MATCH_ALL:
606 : : /* object is a GList of objects; param_getfcn must be called on each one.
607 : : * See if every guid in the predicate is accounted-for in the
608 : : * object list
609 : : */
610 : :
611 : 605 : for (node = pdata->guids; node; node = node->next)
612 : : {
613 : : /* See if this GncGUID matches the object's guid */
614 : 613 : for (o_list = static_cast<GList*>(object); o_list;
615 : 208 : o_list = static_cast<GList*>(o_list->next))
616 : : {
617 : 613 : guid = ((query_guid_getter)getter->param_getfcn) (o_list->data, getter);
618 : 613 : if (guid_equal (static_cast<GncGUID*>(node->data), guid))
619 : 405 : break;
620 : : }
621 : :
622 : : /*
623 : : * If o_list is nullptr, we've walked the whole list without finding
624 : : * a match. Therefore break out now, the match has failed.
625 : : */
626 : 405 : if (o_list == nullptr)
627 : 0 : break;
628 : : }
629 : :
630 : : /*
631 : : * The match is complete. If node == nullptr then we've successfully
632 : : * found a match for all the guids in the predicate. Return
633 : : * appropriately below.
634 : : */
635 : :
636 : 200 : break;
637 : :
638 : 0 : case QOF_GUID_MATCH_LIST_ANY:
639 : : /* object is a single object, getter returns a GList* of GncGUID*
640 : : *
641 : : * See if any GncGUID* in the returned list matches any guid in the
642 : : * predicate match list.
643 : : */
644 : :
645 : 0 : o_list = ((query_glist_getter)getter->param_getfcn) (object, getter);
646 : :
647 : 0 : for (node = o_list; node; node = node->next)
648 : : {
649 : : GList *node2;
650 : :
651 : : /* Search the predicate data for a match */
652 : 0 : for (node2 = pdata->guids; node2; node2 = node2->next)
653 : : {
654 : 0 : if (guid_equal (static_cast<GncGUID*>(node->data),
655 : 0 : static_cast<GncGUID*>(node2->data)))
656 : 0 : break;
657 : : }
658 : :
659 : : /* Check to see if we found a match. If so, break now */
660 : 0 : if (node2 != nullptr)
661 : 0 : break;
662 : : }
663 : :
664 : 0 : g_list_free(o_list);
665 : :
666 : : /* yea, node may point to an invalid location, but that's ok.
667 : : * we're not _USING_ the value, just checking that it's non-nullptr
668 : : */
669 : :
670 : 0 : break;
671 : :
672 : 535379 : default:
673 : : /* object is a single object, getter returns a GncGUID*
674 : : *
675 : : * See if the guid is in the list
676 : : */
677 : :
678 : 535379 : guid = ((query_guid_getter)getter->param_getfcn) (object, getter);
679 : 1710381 : for (node = pdata->guids; node; node = node->next)
680 : : {
681 : 1535783 : if (guid_equal (static_cast<GncGUID*>(node->data), guid))
682 : 360781 : break;
683 : : }
684 : : }
685 : :
686 : 535579 : switch (pdata->options)
687 : : {
688 : 535179 : case QOF_GUID_MATCH_ANY:
689 : : case QOF_GUID_MATCH_LIST_ANY:
690 : 535179 : return (node != nullptr);
691 : : break;
692 : 400 : case QOF_GUID_MATCH_NONE:
693 : : case QOF_GUID_MATCH_ALL:
694 : 400 : return (node == nullptr);
695 : : break;
696 : 0 : case QOF_GUID_MATCH_NULL:
697 : 0 : return ((guid == nullptr) || guid_equal(guid, guid_null()));
698 : : break;
699 : 0 : default:
700 : 0 : PWARN ("bad match type");
701 : 0 : return 0;
702 : : }
703 : : }
704 : :
705 : : static void
706 : 29171 : guid_free_pdata (QofQueryPredData *pd)
707 : : {
708 : 29171 : query_guid_t pdata = (query_guid_t)pd;
709 : : GList *node;
710 : 29171 : VERIFY_PDATA (query_guid_type);
711 : 106646 : for (node = pdata->guids; node; node = node->next)
712 : : {
713 : 77475 : guid_free (static_cast<GncGUID*>(node->data));
714 : : }
715 : 29171 : g_list_free (pdata->guids);
716 : 29171 : g_free (pdata);
717 : : }
718 : :
719 : : static QofQueryPredData *
720 : 22981 : guid_copy_predicate (const QofQueryPredData *pd)
721 : : {
722 : 22981 : const query_guid_t pdata = (const query_guid_t)pd;
723 : 22981 : VERIFY_PDATA_R (query_guid_type);
724 : 22981 : return qof_query_guid_predicate (pdata->options, pdata->guids);
725 : : }
726 : :
727 : : static gboolean
728 : 414 : guid_predicate_equal (const QofQueryPredData *p1, const QofQueryPredData *p2)
729 : : {
730 : 414 : const query_guid_t pd1 = (const query_guid_t) p1;
731 : 414 : const query_guid_t pd2 = (const query_guid_t) p2;
732 : 414 : GList *l1 = pd1->guids, *l2 = pd2->guids;
733 : :
734 : 414 : if (pd1->options != pd2->options) return FALSE;
735 : 1780 : for (; l1 || l2; l1 = l1->next, l2 = l2->next)
736 : : {
737 : 1366 : if (!l1 || !l2)
738 : 0 : return FALSE;
739 : 1366 : if (!guid_equal (static_cast<GncGUID*>(l1->data),
740 : 1366 : static_cast<GncGUID*>(l2->data)))
741 : 0 : return FALSE;
742 : : }
743 : 414 : return TRUE;
744 : : }
745 : :
746 : : QofQueryPredData *
747 : 29181 : qof_query_guid_predicate (QofGuidMatch options, GList *guid_list)
748 : : {
749 : : query_guid_t pdata;
750 : : GList *node;
751 : :
752 : : /* An empty list of guids is only valid when testing for a null GUID value */
753 : 29181 : if (!guid_list)
754 : 0 : g_return_val_if_fail (options == QOF_GUID_MATCH_NULL, nullptr);
755 : :
756 : 29181 : pdata = g_new0 (query_guid_def, 1);
757 : 29181 : pdata->pd.how = QOF_COMPARE_EQUAL;
758 : 29181 : pdata->pd.type_name = query_guid_type;
759 : 29181 : pdata->options = options;
760 : :
761 : 29181 : pdata->guids = g_list_copy (guid_list);
762 : 106666 : for (node = pdata->guids; node; node = node->next)
763 : : {
764 : 77485 : GncGUID *guid = guid_malloc ();
765 : 77485 : *guid = *((GncGUID *)node->data);
766 : 77485 : node->data = guid;
767 : : }
768 : 29181 : return ((QofQueryPredData*)pdata);
769 : : }
770 : :
771 : : /* ================================================================ */
772 : : /* QOF_TYPE_INT32 */
773 : :
774 : : static int
775 : 0 : int32_match_predicate (gpointer object, QofParam *getter,
776 : : QofQueryPredData *pd)
777 : : {
778 : : gint32 val;
779 : 0 : query_int32_t pdata = (query_int32_t)pd;
780 : :
781 : 0 : VERIFY_PREDICATE (query_int32_type);
782 : :
783 : 0 : val = ((query_int32_getter)getter->param_getfcn) (object, getter);
784 : :
785 : 0 : switch (pd->how)
786 : : {
787 : 0 : case QOF_COMPARE_LT:
788 : 0 : return (val < pdata->val);
789 : 0 : case QOF_COMPARE_LTE:
790 : 0 : return (val <= pdata->val);
791 : 0 : case QOF_COMPARE_EQUAL:
792 : 0 : return (val == pdata->val);
793 : 0 : case QOF_COMPARE_GT:
794 : 0 : return (val > pdata->val);
795 : 0 : case QOF_COMPARE_GTE:
796 : 0 : return (val >= pdata->val);
797 : 0 : case QOF_COMPARE_NEQ:
798 : 0 : return (val != pdata->val);
799 : 0 : default:
800 : 0 : PWARN ("bad match type: %d", pd->how);
801 : 0 : return 0;
802 : : }
803 : : }
804 : :
805 : : static int
806 : 0 : int32_compare_func (gpointer a, gpointer b, gint options,
807 : : QofParam *getter)
808 : : {
809 : : gint32 v1, v2;
810 : 0 : g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
811 : :
812 : 0 : v1 = ((query_int32_getter)getter->param_getfcn)(a, getter);
813 : 0 : v2 = ((query_int32_getter)getter->param_getfcn)(b, getter);
814 : :
815 : 0 : if (v1 < v2) return -1;
816 : 0 : if (v1 > v2) return 1;
817 : 0 : return 0;
818 : : }
819 : :
820 : : static void
821 : 1 : int32_free_pdata (QofQueryPredData *pd)
822 : : {
823 : 1 : query_int32_t pdata = (query_int32_t)pd;
824 : 1 : VERIFY_PDATA (query_int32_type);
825 : 1 : g_free (pdata);
826 : : }
827 : :
828 : : static QofQueryPredData *
829 : 0 : int32_copy_predicate (const QofQueryPredData *pd)
830 : : {
831 : 0 : const query_int32_t pdata = (const query_int32_t)pd;
832 : 0 : VERIFY_PDATA_R (query_int32_type);
833 : 0 : return qof_query_int32_predicate (pd->how, pdata->val);
834 : : }
835 : :
836 : : static gboolean
837 : 0 : int32_predicate_equal (const QofQueryPredData *p1, const QofQueryPredData *p2)
838 : : {
839 : 0 : const query_int32_t pd1 = (const query_int32_t) p1;
840 : 0 : const query_int32_t pd2 = (const query_int32_t) p2;
841 : :
842 : 0 : return (pd1->val == pd2->val);
843 : : }
844 : :
845 : : QofQueryPredData *
846 : 1 : qof_query_int32_predicate (QofQueryCompare how, gint32 val)
847 : : {
848 : 1 : query_int32_t pdata = g_new0 (query_int32_def, 1);
849 : 1 : pdata->pd.type_name = query_int32_type;
850 : 1 : pdata->pd.how = how;
851 : 1 : pdata->val = val;
852 : 1 : return ((QofQueryPredData*)pdata);
853 : : }
854 : :
855 : : static char *
856 : 0 : int32_to_string (gpointer object, QofParam *getter)
857 : : {
858 : 0 : gint32 num = ((query_int32_getter)getter->param_getfcn)(object, getter);
859 : :
860 : 0 : return g_strdup_printf ("%d", num);
861 : : }
862 : :
863 : : /* ================================================================ */
864 : : /* QOF_TYPE_INT64 */
865 : :
866 : : static int
867 : 0 : int64_match_predicate (gpointer object, QofParam *getter,
868 : : QofQueryPredData *pd)
869 : : {
870 : : gint64 val;
871 : 0 : query_int64_t pdata = (query_int64_t)pd;
872 : :
873 : 0 : VERIFY_PREDICATE (query_int64_type);
874 : :
875 : 0 : val = ((query_int64_getter)getter->param_getfcn) (object, getter);
876 : :
877 : 0 : switch (pd->how)
878 : : {
879 : 0 : case QOF_COMPARE_LT:
880 : 0 : return (val < pdata->val);
881 : 0 : case QOF_COMPARE_LTE:
882 : 0 : return (val <= pdata->val);
883 : 0 : case QOF_COMPARE_EQUAL:
884 : 0 : return (val == pdata->val);
885 : 0 : case QOF_COMPARE_GT:
886 : 0 : return (val > pdata->val);
887 : 0 : case QOF_COMPARE_GTE:
888 : 0 : return (val >= pdata->val);
889 : 0 : case QOF_COMPARE_NEQ:
890 : 0 : return (val != pdata->val);
891 : 0 : default:
892 : 0 : PWARN ("bad match type: %d", pd->how);
893 : 0 : return 0;
894 : : }
895 : : }
896 : :
897 : : static int
898 : 0 : int64_compare_func (gpointer a, gpointer b, gint options,
899 : : QofParam *getter)
900 : : {
901 : : gint64 v1, v2;
902 : 0 : g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
903 : :
904 : 0 : v1 = ((query_int64_getter)getter->param_getfcn)(a, getter);
905 : 0 : v2 = ((query_int64_getter)getter->param_getfcn)(b, getter);
906 : :
907 : 0 : if (v1 < v2) return -1;
908 : 0 : if (v1 > v2) return 1;
909 : 0 : return 0;
910 : : }
911 : :
912 : : static void
913 : 1 : int64_free_pdata (QofQueryPredData *pd)
914 : : {
915 : 1 : query_int64_t pdata = (query_int64_t)pd;
916 : 1 : VERIFY_PDATA (query_int64_type);
917 : 1 : g_free (pdata);
918 : : }
919 : :
920 : : static QofQueryPredData *
921 : 0 : int64_copy_predicate (const QofQueryPredData *pd)
922 : : {
923 : 0 : const query_int64_t pdata = (const query_int64_t)pd;
924 : 0 : VERIFY_PDATA_R (query_int64_type);
925 : 0 : return qof_query_int64_predicate (pd->how, pdata->val);
926 : : }
927 : :
928 : : static gboolean
929 : 0 : int64_predicate_equal (const QofQueryPredData *p1, const QofQueryPredData *p2)
930 : : {
931 : 0 : const query_int64_t pd1 = (const query_int64_t) p1;
932 : 0 : const query_int64_t pd2 = (const query_int64_t) p2;
933 : :
934 : 0 : return (pd1->val == pd2->val);
935 : : }
936 : :
937 : : QofQueryPredData *
938 : 1 : qof_query_int64_predicate (QofQueryCompare how, gint64 val)
939 : : {
940 : 1 : query_int64_t pdata = g_new0 (query_int64_def, 1);
941 : 1 : pdata->pd.type_name = query_int64_type;
942 : 1 : pdata->pd.how = how;
943 : 1 : pdata->val = val;
944 : 1 : return ((QofQueryPredData*)pdata);
945 : : }
946 : :
947 : : static char *
948 : 0 : int64_to_string (gpointer object, QofParam *getter)
949 : : {
950 : 0 : gint64 num = ((query_int64_getter)getter->param_getfcn)(object, getter);
951 : :
952 : 0 : return g_strdup_printf ("%" G_GINT64_FORMAT, num);
953 : : }
954 : :
955 : : /* ================================================================ */
956 : : /* QOF_TYPE_DOUBLE */
957 : :
958 : : static int
959 : 0 : double_match_predicate (gpointer object, QofParam *getter,
960 : : QofQueryPredData *pd)
961 : : {
962 : : double val;
963 : 0 : query_double_t pdata = (query_double_t)pd;
964 : :
965 : 0 : VERIFY_PREDICATE (query_double_type);
966 : :
967 : 0 : val = ((query_double_getter)getter->param_getfcn) (object, getter);
968 : :
969 : 0 : switch (pd->how)
970 : : {
971 : 0 : case QOF_COMPARE_LT:
972 : 0 : return (val < pdata->val);
973 : 0 : case QOF_COMPARE_LTE:
974 : 0 : return (val <= pdata->val);
975 : 0 : case QOF_COMPARE_EQUAL:
976 : 0 : return (val == pdata->val);
977 : 0 : case QOF_COMPARE_GT:
978 : 0 : return (val > pdata->val);
979 : 0 : case QOF_COMPARE_GTE:
980 : 0 : return (val >= pdata->val);
981 : 0 : case QOF_COMPARE_NEQ:
982 : 0 : return (val != pdata->val);
983 : 0 : default:
984 : 0 : PWARN ("bad match type: %d", pd->how);
985 : 0 : return 0;
986 : : }
987 : : }
988 : :
989 : : static int
990 : 0 : double_compare_func (gpointer a, gpointer b, gint options,
991 : : QofParam *getter)
992 : : {
993 : : double v1, v2;
994 : 0 : g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
995 : :
996 : 0 : v1 = ((query_double_getter)getter->param_getfcn) (a, getter);
997 : 0 : v2 = ((query_double_getter)getter->param_getfcn) (b, getter);
998 : :
999 : 0 : if (v1 < v2) return -1;
1000 : 0 : if (v1 > v2) return 1;
1001 : 0 : return 0;
1002 : : }
1003 : :
1004 : : static void
1005 : 1 : double_free_pdata (QofQueryPredData *pd)
1006 : : {
1007 : 1 : query_double_t pdata = (query_double_t)pd;
1008 : 1 : VERIFY_PDATA (query_double_type);
1009 : 1 : g_free (pdata);
1010 : : }
1011 : :
1012 : : static QofQueryPredData *
1013 : 0 : double_copy_predicate (const QofQueryPredData *pd)
1014 : : {
1015 : 0 : const query_double_t pdata = (const query_double_t)pd;
1016 : 0 : VERIFY_PDATA_R (query_double_type);
1017 : 0 : return qof_query_double_predicate (pd->how, pdata->val);
1018 : : }
1019 : :
1020 : : static gboolean
1021 : 0 : double_predicate_equal (const QofQueryPredData *p1, const QofQueryPredData *p2)
1022 : : {
1023 : 0 : const query_double_t pd1 = (const query_double_t) p1;
1024 : 0 : const query_double_t pd2 = (const query_double_t) p2;
1025 : :
1026 : 0 : return (pd1->val == pd2->val);
1027 : : }
1028 : :
1029 : : QofQueryPredData *
1030 : 1 : qof_query_double_predicate (QofQueryCompare how, double val)
1031 : : {
1032 : 1 : query_double_t pdata = g_new0 (query_double_def, 1);
1033 : 1 : pdata->pd.type_name = query_double_type;
1034 : 1 : pdata->pd.how = how;
1035 : 1 : pdata->val = val;
1036 : 1 : return ((QofQueryPredData*)pdata);
1037 : : }
1038 : :
1039 : : static char *
1040 : 0 : double_to_string (gpointer object, QofParam *getter)
1041 : : {
1042 : 0 : double num = ((query_double_getter)getter->param_getfcn)(object, getter);
1043 : :
1044 : 0 : return g_strdup_printf ("%f", num);
1045 : : }
1046 : :
1047 : : /* QOF_TYPE_BOOLEAN =================================================== */
1048 : :
1049 : : static int
1050 : 1930 : boolean_match_predicate (gpointer object, QofParam *getter,
1051 : : QofQueryPredData *pd)
1052 : : {
1053 : : gboolean val;
1054 : 1930 : query_boolean_t pdata = (query_boolean_t)pd;
1055 : :
1056 : 1930 : VERIFY_PREDICATE (query_boolean_type);
1057 : :
1058 : 1930 : val = ((query_boolean_getter)getter->param_getfcn) (object, getter);
1059 : :
1060 : 1930 : switch (pd->how)
1061 : : {
1062 : 1930 : case QOF_COMPARE_EQUAL:
1063 : 1930 : return (val == pdata->val);
1064 : 0 : case QOF_COMPARE_NEQ:
1065 : 0 : return (val != pdata->val);
1066 : 0 : default:
1067 : 0 : PWARN ("bad match type: %d", pd->how);
1068 : 0 : return 0;
1069 : : }
1070 : : }
1071 : :
1072 : : static int
1073 : 0 : boolean_compare_func (gpointer a, gpointer b, gint options,
1074 : : QofParam *getter)
1075 : : {
1076 : : gboolean va, vb;
1077 : 0 : g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
1078 : 0 : va = ((query_boolean_getter)getter->param_getfcn) (a, getter);
1079 : 0 : vb = ((query_boolean_getter)getter->param_getfcn) (b, getter);
1080 : 0 : if (!va && vb) return -1;
1081 : 0 : if (va && !vb) return 1;
1082 : 0 : return 0;
1083 : : }
1084 : :
1085 : : static void
1086 : 550 : boolean_free_pdata (QofQueryPredData *pd)
1087 : : {
1088 : 550 : query_boolean_t pdata = (query_boolean_t)pd;
1089 : 550 : VERIFY_PDATA (query_boolean_type);
1090 : 550 : g_free (pdata);
1091 : : }
1092 : :
1093 : : static QofQueryPredData *
1094 : 341 : boolean_copy_predicate (const QofQueryPredData *pd)
1095 : : {
1096 : 341 : const query_boolean_t pdata = (const query_boolean_t)pd;
1097 : 341 : VERIFY_PDATA_R (query_boolean_type);
1098 : 341 : return qof_query_boolean_predicate (pd->how, pdata->val);
1099 : : }
1100 : :
1101 : : static gboolean
1102 : 0 : boolean_predicate_equal (const QofQueryPredData *p1, const QofQueryPredData *p2)
1103 : : {
1104 : 0 : const query_boolean_t pd1 = (const query_boolean_t) p1;
1105 : 0 : const query_boolean_t pd2 = (const query_boolean_t) p2;
1106 : :
1107 : 0 : return (pd1->val == pd2->val);
1108 : : }
1109 : :
1110 : : QofQueryPredData *
1111 : 550 : qof_query_boolean_predicate (QofQueryCompare how, gboolean val)
1112 : : {
1113 : : query_boolean_t pdata;
1114 : 550 : g_return_val_if_fail (how == QOF_COMPARE_EQUAL || how == QOF_COMPARE_NEQ, nullptr);
1115 : :
1116 : 550 : pdata = g_new0 (query_boolean_def, 1);
1117 : 550 : pdata->pd.type_name = query_boolean_type;
1118 : 550 : pdata->pd.how = how;
1119 : 550 : pdata->val = val;
1120 : 550 : return ((QofQueryPredData*)pdata);
1121 : : }
1122 : :
1123 : : static char *
1124 : 0 : boolean_to_string (gpointer object, QofParam *getter)
1125 : : {
1126 : 0 : gboolean num = ((query_boolean_getter)getter->param_getfcn)(object, getter);
1127 : :
1128 : 0 : return g_strdup_printf ("%s", (num ? "X" : ""));
1129 : : }
1130 : :
1131 : : /* QOF_TYPE_CHAR =================================================== */
1132 : :
1133 : : static int
1134 : 212984 : char_match_predicate (gpointer object, QofParam *getter,
1135 : : QofQueryPredData *pd)
1136 : : {
1137 : : char c;
1138 : 212984 : query_char_t pdata = (query_char_t)pd;
1139 : :
1140 : 212984 : VERIFY_PREDICATE (query_char_type);
1141 : :
1142 : 212984 : c = ((query_char_getter)getter->param_getfcn) (object, getter);
1143 : :
1144 : 212984 : switch (pdata->options)
1145 : : {
1146 : 212984 : case QOF_CHAR_MATCH_ANY:
1147 : 212984 : if (strchr (pdata->char_list, c)) return 1;
1148 : 6402 : return 0;
1149 : 0 : case QOF_CHAR_MATCH_NONE:
1150 : 0 : if (!strchr (pdata->char_list, c)) return 1;
1151 : 0 : return 0;
1152 : 0 : default:
1153 : 0 : PWARN ("bad match type");
1154 : 0 : return 0;
1155 : : }
1156 : : }
1157 : :
1158 : : static int
1159 : 0 : char_compare_func (gpointer a, gpointer b, gint options, QofParam *getter)
1160 : : {
1161 : : char va, vb;
1162 : 0 : g_return_val_if_fail (a && b && getter && getter->param_getfcn, COMPARE_ERROR);
1163 : 0 : va = ((query_char_getter)getter->param_getfcn)(a, getter);
1164 : 0 : vb = ((query_char_getter)getter->param_getfcn)(b, getter);
1165 : 0 : return (va - vb);
1166 : : }
1167 : :
1168 : : static void
1169 : 9177 : char_free_pdata (QofQueryPredData *pd)
1170 : : {
1171 : 9177 : query_char_t pdata = (query_char_t)pd;
1172 : 9177 : VERIFY_PDATA (query_char_type);
1173 : 9177 : g_free (pdata->char_list);
1174 : 9177 : g_free (pdata);
1175 : : }
1176 : :
1177 : : static QofQueryPredData *
1178 : 7153 : char_copy_predicate (const QofQueryPredData *pd)
1179 : : {
1180 : 7153 : const query_char_t pdata = (const query_char_t)pd;
1181 : 7153 : VERIFY_PDATA_R (query_char_type);
1182 : 7153 : return qof_query_char_predicate (pdata->options, pdata->char_list);
1183 : : }
1184 : :
1185 : : static gboolean
1186 : 192 : char_predicate_equal (const QofQueryPredData *p1, const QofQueryPredData *p2)
1187 : : {
1188 : 192 : const query_char_t pd1 = (const query_char_t) p1;
1189 : 192 : const query_char_t pd2 = (const query_char_t) p2;
1190 : :
1191 : 192 : if (pd1->options != pd2->options) return FALSE;
1192 : 192 : return (g_strcmp0 (pd1->char_list, pd2->char_list) == 0);
1193 : : }
1194 : :
1195 : : QofQueryPredData *
1196 : 9183 : qof_query_char_predicate (QofCharMatch options, const char *chars)
1197 : : {
1198 : : query_char_t pdata;
1199 : 9183 : g_return_val_if_fail (chars, nullptr);
1200 : 9183 : pdata = g_new0 (query_char_def, 1);
1201 : 9183 : pdata->pd.type_name = query_char_type;
1202 : 9183 : pdata->pd.how = QOF_COMPARE_EQUAL;
1203 : 9183 : pdata->options = options;
1204 : 9183 : pdata->char_list = g_strdup (chars);
1205 : 9183 : return ((QofQueryPredData*)pdata);
1206 : : }
1207 : :
1208 : : gboolean
1209 : 0 : qof_query_char_predicate_get_char (const QofQueryPredData *pd, char **chars)
1210 : : {
1211 : 0 : const query_char_t pdata = (const query_char_t)pd;
1212 : :
1213 : 0 : if (pdata->pd.type_name != query_char_type)
1214 : 0 : return FALSE;
1215 : :
1216 : 0 : *chars = g_strdup (pdata->char_list);
1217 : 0 : return TRUE;
1218 : : }
1219 : :
1220 : : static char *
1221 : 0 : char_to_string (gpointer object, QofParam *getter)
1222 : : {
1223 : 0 : char num = ((query_char_getter)getter->param_getfcn)(object, getter);
1224 : :
1225 : 0 : return g_strdup_printf ("%c", num);
1226 : : }
1227 : :
1228 : : /* QOF_TYPE_COLLECT =============================================== */
1229 : :
1230 : : static int
1231 : 0 : collect_match_predicate (gpointer object, QofParam *getter,
1232 : : QofQueryPredData *pd)
1233 : : {
1234 : : query_coll_t pdata;
1235 : : GList *node, *node2, *o_list;
1236 : : const GncGUID *guid;
1237 : :
1238 : 0 : pdata = (query_coll_t)pd;
1239 : 0 : VERIFY_PREDICATE (query_collect_type);
1240 : 0 : guid = nullptr;
1241 : 0 : switch (pdata->options)
1242 : : {
1243 : 0 : case QOF_GUID_MATCH_ALL :
1244 : : {
1245 : 0 : for (node = pdata->guids; node; node = node->next)
1246 : : {
1247 : 0 : for (o_list = static_cast<GList*>(object); o_list;
1248 : 0 : o_list = static_cast<GList*>(o_list->next))
1249 : : {
1250 : 0 : guid = ((query_guid_getter)getter->param_getfcn)
1251 : 0 : (o_list->data, getter);
1252 : 0 : if (guid_equal (static_cast<GncGUID*>(node->data), guid))
1253 : : {
1254 : 0 : break;
1255 : : }
1256 : : }
1257 : 0 : if (o_list == nullptr)
1258 : : {
1259 : 0 : break;
1260 : : }
1261 : : }
1262 : 0 : break;
1263 : : }
1264 : 0 : case QOF_GUID_MATCH_LIST_ANY :
1265 : : {
1266 : 0 : o_list = ((query_glist_getter)getter->param_getfcn) (object, getter);
1267 : 0 : for (node = o_list; node; node = node->next)
1268 : : {
1269 : 0 : for (node2 = pdata->guids; node2; node2 = node2->next)
1270 : : {
1271 : 0 : if (guid_equal (static_cast<GncGUID*>(node->data),
1272 : 0 : static_cast<GncGUID*>(node2->data)))
1273 : : {
1274 : 0 : break;
1275 : : }
1276 : : }
1277 : 0 : if (node2 != nullptr)
1278 : : {
1279 : 0 : break;
1280 : : }
1281 : : }
1282 : 0 : g_list_free(o_list);
1283 : 0 : break;
1284 : : }
1285 : 0 : default :
1286 : : {
1287 : 0 : guid = ((query_guid_getter)getter->param_getfcn) (object, getter);
1288 : 0 : for (node = pdata->guids; node; node = node->next)
1289 : : {
1290 : 0 : if (guid_equal (static_cast<GncGUID*>(node->data), guid))
1291 : : {
1292 : 0 : break;
1293 : : }
1294 : : }
1295 : : }
1296 : 0 : switch (pdata->options)
1297 : : {
1298 : 0 : case QOF_GUID_MATCH_ANY :
1299 : : case QOF_GUID_MATCH_LIST_ANY :
1300 : : {
1301 : 0 : return (node != nullptr);
1302 : : break;
1303 : : }
1304 : 0 : case QOF_GUID_MATCH_NONE :
1305 : : case QOF_GUID_MATCH_ALL :
1306 : : {
1307 : 0 : return (node == nullptr);
1308 : : break;
1309 : : }
1310 : 0 : case QOF_GUID_MATCH_NULL :
1311 : : {
1312 : 0 : return ((guid == nullptr) || guid_equal(guid, guid_null()));
1313 : : break;
1314 : : }
1315 : 0 : default :
1316 : : {
1317 : 0 : PWARN ("bad match type");
1318 : 0 : return 0;
1319 : : }
1320 : : }
1321 : : }
1322 : 0 : return 0;
1323 : : }
1324 : :
1325 : : static int
1326 : 0 : collect_compare_func (gpointer a, gpointer b, gint options, QofParam *getter)
1327 : : {
1328 : : gint result;
1329 : : QofCollection *c1, *c2;
1330 : :
1331 : 0 : c1 = ((query_collect_getter)getter->param_getfcn) (a, getter);
1332 : 0 : c2 = ((query_collect_getter)getter->param_getfcn) (b, getter);
1333 : 0 : result = qof_collection_compare(c1, c2);
1334 : 0 : return result;
1335 : : }
1336 : :
1337 : : static void
1338 : 0 : collect_free_pdata (QofQueryPredData *pd)
1339 : : {
1340 : : query_coll_t pdata;
1341 : : GList *node;
1342 : :
1343 : 0 : node = nullptr;
1344 : 0 : pdata = (query_coll_t) pd;
1345 : 0 : VERIFY_PDATA (query_collect_type);
1346 : 0 : for (node = pdata->guids; node; node = node->next)
1347 : : {
1348 : 0 : guid_free (static_cast<GncGUID*>(node->data));
1349 : : }
1350 : 0 : qof_collection_destroy(pdata->coll);
1351 : 0 : g_list_free (pdata->guids);
1352 : 0 : g_free (pdata);
1353 : : }
1354 : :
1355 : : static QofQueryPredData *
1356 : 0 : collect_copy_predicate (const QofQueryPredData *pd)
1357 : : {
1358 : 0 : const query_coll_t pdata = (const query_coll_t) pd;
1359 : :
1360 : 0 : VERIFY_PDATA_R (query_collect_type);
1361 : 0 : return qof_query_collect_predicate (pdata->options, pdata->coll);
1362 : : }
1363 : :
1364 : : static gboolean
1365 : 0 : collect_predicate_equal (const QofQueryPredData *p1, const QofQueryPredData *p2)
1366 : : {
1367 : 0 : const query_coll_t pd1 = (const query_coll_t) p1;
1368 : 0 : const query_coll_t pd2 = (const query_coll_t) p2;
1369 : : gint result;
1370 : :
1371 : 0 : result = qof_collection_compare(pd1->coll, pd2->coll);
1372 : 0 : if (result == 0)
1373 : : {
1374 : 0 : return TRUE;
1375 : : }
1376 : 0 : return FALSE;
1377 : : }
1378 : :
1379 : : static void
1380 : 0 : query_collect_cb(QofInstance* ent, gpointer user_data)
1381 : : {
1382 : : query_coll_t pdata;
1383 : : GncGUID *guid;
1384 : :
1385 : 0 : guid = (GncGUID*)qof_entity_get_guid(ent);
1386 : 0 : pdata = (query_coll_t)user_data;
1387 : 0 : pdata->guids = g_list_append(pdata->guids, guid);
1388 : 0 : }
1389 : :
1390 : : QofQueryPredData *
1391 : 0 : qof_query_collect_predicate (QofGuidMatch options, QofCollection *coll)
1392 : : {
1393 : : query_coll_t pdata;
1394 : :
1395 : 0 : g_return_val_if_fail (coll, nullptr);
1396 : 0 : pdata = g_new0 (query_coll_def, 1);
1397 : 0 : pdata->pd.type_name = query_collect_type;
1398 : 0 : pdata->options = options;
1399 : 0 : qof_collection_foreach(coll, query_collect_cb, pdata);
1400 : 0 : if (nullptr == pdata->guids)
1401 : : {
1402 : 0 : return nullptr;
1403 : : }
1404 : 0 : return ((QofQueryPredData*)pdata);
1405 : : }
1406 : :
1407 : : /* QOF_TYPE_CHOICE */
1408 : :
1409 : : static int
1410 : 0 : choice_match_predicate (gpointer object, QofParam *getter,
1411 : : QofQueryPredData *pd)
1412 : : {
1413 : 0 : query_choice_t pdata = (query_choice_t)pd;
1414 : : GList *node, *o_list;
1415 : 0 : const GncGUID *guid = nullptr;
1416 : :
1417 : 0 : VERIFY_PREDICATE (query_choice_type);
1418 : :
1419 : 0 : switch (pdata->options)
1420 : : {
1421 : :
1422 : 0 : case QOF_GUID_MATCH_ALL:
1423 : : /* object is a GList of objects; param_getfcn must be called on each one.
1424 : : * See if every guid in the predicate is accounted-for in the
1425 : : * object list
1426 : : */
1427 : :
1428 : 0 : for (node = pdata->guids; node; node = node->next)
1429 : : {
1430 : : /* See if this GncGUID matches the object's guid */
1431 : 0 : for (o_list = static_cast<GList*>(object); o_list;
1432 : 0 : o_list = static_cast<GList*>(o_list->next))
1433 : : {
1434 : 0 : guid = ((query_choice_getter)getter->param_getfcn) (o_list->data, getter);
1435 : 0 : if (guid_equal (static_cast<GncGUID*>(node->data), guid))
1436 : 0 : break;
1437 : : }
1438 : :
1439 : : /*
1440 : : * If o_list is nullptr, we've walked the whole list without finding
1441 : : * a match. Therefore break out now, the match has failed.
1442 : : */
1443 : 0 : if (o_list == nullptr)
1444 : 0 : break;
1445 : : }
1446 : :
1447 : : /*
1448 : : * The match is complete. If node == nullptr then we've successfully
1449 : : * found a match for all the guids in the predicate. Return
1450 : : * appropriately below.
1451 : : */
1452 : :
1453 : 0 : break;
1454 : :
1455 : 0 : case QOF_GUID_MATCH_LIST_ANY:
1456 : :
1457 : 0 : o_list = ((query_glist_getter)getter->param_getfcn) (object, getter);
1458 : :
1459 : 0 : for (node = o_list; node; node = node->next)
1460 : : {
1461 : : GList *node2;
1462 : :
1463 : 0 : for (node2 = pdata->guids; node2; node2 = node2->next)
1464 : : {
1465 : 0 : if (guid_equal (static_cast<GncGUID*>(node->data),
1466 : 0 : static_cast<GncGUID*>(node2->data)))
1467 : 0 : break;
1468 : : }
1469 : :
1470 : 0 : if (node2 != nullptr)
1471 : 0 : break;
1472 : : }
1473 : :
1474 : 0 : g_list_free(o_list);
1475 : :
1476 : 0 : break;
1477 : :
1478 : 0 : default:
1479 : : /* object is a single object, getter returns a GncGUID*
1480 : : *
1481 : : * See if the guid is in the list
1482 : : */
1483 : :
1484 : 0 : guid = ((query_choice_getter)getter->param_getfcn) (object, getter);
1485 : 0 : for (node = pdata->guids; node; node = node->next)
1486 : : {
1487 : 0 : if (guid_equal (static_cast<GncGUID*>(node->data), guid))
1488 : 0 : break;
1489 : : }
1490 : : }
1491 : :
1492 : 0 : switch (pdata->options)
1493 : : {
1494 : 0 : case QOF_GUID_MATCH_ANY:
1495 : : case QOF_GUID_MATCH_LIST_ANY:
1496 : 0 : return (node != nullptr);
1497 : : break;
1498 : 0 : case QOF_GUID_MATCH_NONE:
1499 : : case QOF_GUID_MATCH_ALL:
1500 : 0 : return (node == nullptr);
1501 : : break;
1502 : 0 : case QOF_GUID_MATCH_NULL:
1503 : 0 : return ((guid == nullptr) || guid_equal(guid, guid_null()));
1504 : : break;
1505 : 0 : default:
1506 : 0 : PWARN ("bad match type");
1507 : 0 : return 0;
1508 : : }
1509 : : }
1510 : :
1511 : : static void
1512 : 0 : choice_free_pdata (QofQueryPredData *pd)
1513 : : {
1514 : 0 : query_choice_t pdata = (query_choice_t)pd;
1515 : : GList *node;
1516 : 0 : VERIFY_PDATA (query_choice_type);
1517 : 0 : for (node = pdata->guids; node; node = node->next)
1518 : : {
1519 : 0 : guid_free (static_cast<GncGUID*>(node->data));
1520 : : }
1521 : 0 : g_list_free (pdata->guids);
1522 : 0 : g_free (pdata);
1523 : : }
1524 : :
1525 : : static QofQueryPredData *
1526 : 0 : choice_copy_predicate (const QofQueryPredData *pd)
1527 : : {
1528 : 0 : const query_choice_t pdata = (const query_choice_t)pd;
1529 : 0 : VERIFY_PDATA_R (query_choice_type);
1530 : 0 : return qof_query_choice_predicate (pdata->options, pdata->guids);
1531 : : }
1532 : :
1533 : : static gboolean
1534 : 0 : choice_predicate_equal (const QofQueryPredData *p1, const QofQueryPredData *p2)
1535 : : {
1536 : 0 : const query_choice_t pd1 = (const query_choice_t) p1;
1537 : 0 : const query_choice_t pd2 = (const query_choice_t) p2;
1538 : 0 : GList *l1 = pd1->guids, *l2 = pd2->guids;
1539 : :
1540 : 0 : if (pd1->options != pd2->options) return FALSE;
1541 : 0 : for (; l1 || l2; l1 = l1->next, l2 = l2->next)
1542 : : {
1543 : 0 : if (!l1 || !l2)
1544 : 0 : return FALSE;
1545 : 0 : if (!guid_equal (static_cast<GncGUID*>(l1->data),
1546 : 0 : static_cast<GncGUID*>(l2->data)))
1547 : 0 : return FALSE;
1548 : : }
1549 : 0 : return TRUE;
1550 : : }
1551 : :
1552 : : QofQueryPredData *
1553 : 0 : qof_query_choice_predicate (QofGuidMatch options, GList *guid_list)
1554 : : {
1555 : : query_choice_t pdata;
1556 : : GList *node;
1557 : :
1558 : 0 : if (nullptr == guid_list) return nullptr;
1559 : :
1560 : 0 : pdata = g_new0 (query_choice_def, 1);
1561 : 0 : pdata->pd.how = QOF_COMPARE_EQUAL;
1562 : 0 : pdata->pd.type_name = query_choice_type;
1563 : 0 : pdata->options = options;
1564 : :
1565 : 0 : pdata->guids = g_list_copy (guid_list);
1566 : 0 : for (node = pdata->guids; node; node = node->next)
1567 : : {
1568 : 0 : GncGUID *guid = guid_malloc ();
1569 : 0 : *guid = *((GncGUID *)node->data);
1570 : 0 : node->data = guid;
1571 : : }
1572 : 0 : return ((QofQueryPredData*)pdata);
1573 : : }
1574 : :
1575 : :
1576 : : /* initialization ================================================== */
1577 : : /** This function registers a new Core Object with the QofQuery
1578 : : * subsystem. It maps the "core_name" object to the given
1579 : : * query_predicate, predicate_copy, and predicate_data_free functions.
1580 : : *
1581 : : * An example:
1582 : : * qof_query_register_core_object (QOF_TYPE_STRING, string_match_predicate,
1583 : : * string_compare_fcn, string_free_pdata,
1584 : : * string_print_fcn, pred_equal_fcn);
1585 : : */
1586 : :
1587 : :
1588 : : static void
1589 : 1440 : qof_query_register_core_object (QofType core_name,
1590 : : QofQueryPredicateFunc pred,
1591 : : QofCompareFunc comp,
1592 : : QueryPredicateCopyFunc copy,
1593 : : QueryPredDataFree pd_free,
1594 : : QueryToString toString,
1595 : : QueryPredicateEqual pred_equal)
1596 : : {
1597 : 1440 : g_return_if_fail (core_name);
1598 : 1440 : g_return_if_fail (*core_name != '\0');
1599 : :
1600 : 1440 : if (pred)
1601 : 1440 : g_hash_table_insert (predTable, (char *)core_name,
1602 : : reinterpret_cast<void*>(pred));
1603 : :
1604 : 1440 : if (comp)
1605 : 1200 : g_hash_table_insert (cmpTable, (char *)core_name,
1606 : : reinterpret_cast<void*>(comp));
1607 : :
1608 : 1440 : if (copy)
1609 : 1440 : g_hash_table_insert (copyTable, (char *)core_name,
1610 : : reinterpret_cast<void*>(copy));
1611 : :
1612 : 1440 : if (pd_free)
1613 : 1440 : g_hash_table_insert (freeTable, (char *)core_name,
1614 : : reinterpret_cast<void*>(pd_free));
1615 : :
1616 : 1440 : if (toString)
1617 : 1080 : g_hash_table_insert (toStringTable, (char *)core_name,
1618 : : reinterpret_cast<void*>(toString));
1619 : :
1620 : 1440 : if (pred_equal)
1621 : 1440 : g_hash_table_insert (predEqualTable, (char *)core_name,
1622 : : reinterpret_cast<void*>(pred_equal));
1623 : : }
1624 : :
1625 : 120 : static void init_tables (void)
1626 : : {
1627 : : unsigned int i;
1628 : : struct
1629 : : {
1630 : : QofType name;
1631 : : QofQueryPredicateFunc pred;
1632 : : QofCompareFunc comp;
1633 : : QueryPredicateCopyFunc copy;
1634 : : QueryPredDataFree pd_free;
1635 : : QueryToString toString;
1636 : : QueryPredicateEqual pred_equal;
1637 : 120 : } knownTypes[] =
1638 : : {
1639 : : {
1640 : : QOF_TYPE_STRING, string_match_predicate, string_compare_func,
1641 : : string_copy_predicate, string_free_pdata, string_to_string,
1642 : : string_predicate_equal
1643 : : },
1644 : : {
1645 : : QOF_TYPE_DATE, date_match_predicate, date_compare_func,
1646 : : date_copy_predicate, date_free_pdata, date_to_string,
1647 : : date_predicate_equal
1648 : : },
1649 : : {
1650 : : QOF_TYPE_DEBCRED, numeric_match_predicate, numeric_compare_func,
1651 : : numeric_copy_predicate, numeric_free_pdata, debcred_to_string,
1652 : : numeric_predicate_equal
1653 : : },
1654 : : {
1655 : : QOF_TYPE_NUMERIC, numeric_match_predicate, numeric_compare_func,
1656 : : numeric_copy_predicate, numeric_free_pdata, numeric_to_string,
1657 : : numeric_predicate_equal
1658 : : },
1659 : : {
1660 : : QOF_TYPE_GUID, guid_match_predicate, nullptr,
1661 : : guid_copy_predicate, guid_free_pdata, nullptr,
1662 : : guid_predicate_equal
1663 : : },
1664 : : {
1665 : : QOF_TYPE_INT32, int32_match_predicate, int32_compare_func,
1666 : : int32_copy_predicate, int32_free_pdata, int32_to_string,
1667 : : int32_predicate_equal
1668 : : },
1669 : : {
1670 : : QOF_TYPE_INT64, int64_match_predicate, int64_compare_func,
1671 : : int64_copy_predicate, int64_free_pdata, int64_to_string,
1672 : : int64_predicate_equal
1673 : : },
1674 : : {
1675 : : QOF_TYPE_DOUBLE, double_match_predicate, double_compare_func,
1676 : : double_copy_predicate, double_free_pdata, double_to_string,
1677 : : double_predicate_equal
1678 : : },
1679 : : {
1680 : : QOF_TYPE_BOOLEAN, boolean_match_predicate, boolean_compare_func,
1681 : : boolean_copy_predicate, boolean_free_pdata, boolean_to_string,
1682 : : boolean_predicate_equal
1683 : : },
1684 : : {
1685 : : QOF_TYPE_CHAR, char_match_predicate, char_compare_func,
1686 : : char_copy_predicate, char_free_pdata, char_to_string,
1687 : : char_predicate_equal
1688 : : },
1689 : : {
1690 : : QOF_TYPE_COLLECT, collect_match_predicate, collect_compare_func,
1691 : : collect_copy_predicate, collect_free_pdata, nullptr,
1692 : : collect_predicate_equal
1693 : : },
1694 : : {
1695 : : QOF_TYPE_CHOICE, choice_match_predicate, nullptr,
1696 : : choice_copy_predicate, choice_free_pdata, nullptr, choice_predicate_equal
1697 : : },
1698 : : };
1699 : :
1700 : : /* Register the known data types */
1701 : 1560 : for (i = 0; i < (sizeof(knownTypes) / sizeof(*knownTypes)); i++)
1702 : : {
1703 : 1440 : qof_query_register_core_object (knownTypes[i].name,
1704 : : knownTypes[i].pred,
1705 : : knownTypes[i].comp,
1706 : : knownTypes[i].copy,
1707 : : knownTypes[i].pd_free,
1708 : : knownTypes[i].toString,
1709 : : knownTypes[i].pred_equal);
1710 : : }
1711 : 120 : }
1712 : :
1713 : : static QueryPredicateCopyFunc
1714 : 68672 : qof_query_copy_predicate (QofType type)
1715 : : {
1716 : : QueryPredicateCopyFunc rc;
1717 : 68672 : g_return_val_if_fail (type, nullptr);
1718 : 68672 : rc = reinterpret_cast<QueryPredicateCopyFunc>(g_hash_table_lookup (copyTable, type));
1719 : 68672 : return rc;
1720 : : }
1721 : :
1722 : : static QueryPredDataFree
1723 : 84534 : qof_query_predicate_free (QofType type)
1724 : : {
1725 : 84534 : g_return_val_if_fail (type, nullptr);
1726 : 84534 : return reinterpret_cast<QueryPredDataFree>(g_hash_table_lookup (freeTable, type));
1727 : : }
1728 : :
1729 : : /********************************************************************/
1730 : : /* PUBLISHED API FUNCTIONS */
1731 : :
1732 : 128 : void qof_query_core_init (void)
1733 : : {
1734 : : /* Only let us initialize once */
1735 : 128 : if (initialized) return;
1736 : 120 : initialized = TRUE;
1737 : :
1738 : : /* Create the tables */
1739 : 120 : predTable = g_hash_table_new (g_str_hash, g_str_equal);
1740 : 120 : cmpTable = g_hash_table_new (g_str_hash, g_str_equal);
1741 : 120 : copyTable = g_hash_table_new (g_str_hash, g_str_equal);
1742 : 120 : freeTable = g_hash_table_new (g_str_hash, g_str_equal);
1743 : 120 : toStringTable = g_hash_table_new (g_str_hash, g_str_equal);
1744 : 120 : predEqualTable = g_hash_table_new (g_str_hash, g_str_equal);
1745 : :
1746 : 120 : init_tables ();
1747 : : }
1748 : :
1749 : 54 : void qof_query_core_shutdown (void)
1750 : : {
1751 : 54 : if (!initialized) return;
1752 : 54 : initialized = FALSE;
1753 : :
1754 : 54 : g_hash_table_destroy (predTable);
1755 : 54 : g_hash_table_destroy (cmpTable);
1756 : 54 : g_hash_table_destroy (copyTable);
1757 : 54 : g_hash_table_destroy (freeTable);
1758 : 54 : g_hash_table_destroy (toStringTable);
1759 : 54 : g_hash_table_destroy (predEqualTable);
1760 : : }
1761 : :
1762 : : QofQueryPredicateFunc
1763 : 13006 : qof_query_core_get_predicate (QofType type)
1764 : : {
1765 : 13006 : g_return_val_if_fail (type, nullptr);
1766 : 13006 : return reinterpret_cast<QofQueryPredicateFunc>(g_hash_table_lookup (predTable, type));
1767 : : }
1768 : :
1769 : : QofCompareFunc
1770 : 106 : qof_query_core_get_compare (QofType type)
1771 : : {
1772 : 106 : g_return_val_if_fail (type, nullptr);
1773 : 106 : return reinterpret_cast<QofCompareFunc>(g_hash_table_lookup (cmpTable, type));
1774 : : }
1775 : :
1776 : : void
1777 : 84534 : qof_query_core_predicate_free (QofQueryPredData *pdata)
1778 : : {
1779 : : QueryPredDataFree free_fcn;
1780 : :
1781 : 84534 : g_return_if_fail (pdata);
1782 : 84534 : g_return_if_fail (pdata->type_name);
1783 : :
1784 : 84534 : free_fcn = qof_query_predicate_free (pdata->type_name);
1785 : 84534 : free_fcn (pdata);
1786 : : }
1787 : :
1788 : : QofQueryPredData *
1789 : 68672 : qof_query_core_predicate_copy (const QofQueryPredData *pdata)
1790 : : {
1791 : : QueryPredicateCopyFunc copy;
1792 : :
1793 : 68672 : g_return_val_if_fail (pdata, nullptr);
1794 : 68672 : g_return_val_if_fail (pdata->type_name, nullptr);
1795 : :
1796 : 68672 : copy = qof_query_copy_predicate (pdata->type_name);
1797 : 68672 : return (copy (pdata));
1798 : : }
1799 : :
1800 : : char *
1801 : 0 : qof_query_core_to_string (QofType type, gpointer object,
1802 : : QofParam *getter)
1803 : : {
1804 : : QueryToString toString;
1805 : :
1806 : 0 : g_return_val_if_fail (type, nullptr);
1807 : 0 : g_return_val_if_fail (object, nullptr);
1808 : 0 : g_return_val_if_fail (getter, nullptr);
1809 : :
1810 : 0 : toString = reinterpret_cast<QueryToString>(g_hash_table_lookup (toStringTable, type));
1811 : 0 : g_return_val_if_fail (toString, nullptr);
1812 : :
1813 : 0 : return toString (object, getter);
1814 : : }
1815 : :
1816 : : gboolean
1817 : 1809 : qof_query_core_predicate_equal (const QofQueryPredData *p1, const QofQueryPredData *p2)
1818 : : {
1819 : : QueryPredicateEqual pred_equal;
1820 : :
1821 : 1809 : if (p1 == p2) return TRUE;
1822 : 1809 : if (!p1 || !p2) return FALSE;
1823 : :
1824 : 1809 : if (p1->how != p2->how) return FALSE;
1825 : 1809 : if (g_strcmp0 (p1->type_name, p2->type_name)) return FALSE;
1826 : :
1827 : 1809 : pred_equal = reinterpret_cast<QueryPredicateEqual>(g_hash_table_lookup (predEqualTable, p1->type_name));
1828 : 1809 : g_return_val_if_fail (pred_equal, FALSE);
1829 : :
1830 : 1809 : return pred_equal (p1, p2);
1831 : : }
|