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

Generated by: LCOV version 2.0-1