LCOV - code coverage report
Current view: top level - libgnucash/engine - qofquerycore.cpp (source / functions) Coverage Total Hit
Test: gnucash.info Lines: 53.5 % 693 371
Test Date: 2026-07-03 16:23:28 Functions: 62.7 % 83 52
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

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

Generated by: LCOV version 2.0-1