LCOV - code coverage report
Current view: top level - libgnucash/engine - qofobject.cpp (source / functions) Coverage Total Hit
Test: gnucash.info Lines: 97.6 % 123 120
Test Date: 2026-11-02 18:19:43 Functions: 100.0 % 18 18
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /********************************************************************\
       2              :  * qofobject.c -- the Core Object Registration/Lookup Interface     *
       3              :  * This program is free software; you can redistribute it and/or    *
       4              :  * modify it under the terms of the GNU General Public License as   *
       5              :  * published by the Free Software Foundation; either version 2 of   *
       6              :  * the License, or (at your option) any later version.              *
       7              :  *                                                                  *
       8              :  * This program is distributed in the hope that it will be useful,  *
       9              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
      10              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
      11              :  * GNU General Public License for more details.                     *
      12              :  *                                                                  *
      13              :  * You should have received a copy of the GNU General Public License*
      14              :  * along with this program; if not, contact:                        *
      15              :  *                                                                  *
      16              :  * Free Software Foundation           Voice:  +1-617-542-5942       *
      17              :  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
      18              :  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
      19              :  *                                                                  *
      20              : \********************************************************************/
      21              : /*
      22              :  * qofobject.c -- the Core Object Object Registry
      23              :  * Copyright (C) 2001 Derek Atkins
      24              :  * Author: Derek Atkins <warlord@MIT.EDU>
      25              :  */
      26              : #include <config.h>
      27              : #include <glib.h>
      28              : 
      29              : #include "qof.h"
      30              : #include "qofobject-p.h"
      31              : 
      32              : static QofLogModule log_module = QOF_MOD_OBJECT;
      33              : 
      34              : static gboolean object_is_initialized = FALSE;
      35              : static GList *object_modules = nullptr;
      36              : static GList *book_list = nullptr;
      37              : 
      38              : /*
      39              :  * These getters are used in tests to reach static vars from outside
      40              :  * They should be removed when no longer needed
      41              :  */
      42              : 
      43              : extern "C"
      44              : {
      45              : 
      46              : GList* get_object_modules( void );
      47              : GList* get_book_list( void );
      48              : }
      49              : 
      50              : GList*
      51           30 : get_object_modules( void )
      52              : {
      53           30 :     return object_modules;
      54              : }
      55              : 
      56              : GList*
      57           12 : get_book_list( void )
      58              : {
      59           12 :     return book_list;
      60              : }
      61              : 
      62              : /*********/
      63              : 
      64              : gpointer
      65            4 : qof_object_new_instance (QofIdTypeConst type_name, QofBook *book)
      66              : {
      67              :     const QofObject *obj;
      68              : 
      69            4 :     if (!type_name) return nullptr;
      70              : 
      71            3 :     obj = qof_object_lookup (type_name);
      72            3 :     if (!obj) return nullptr;
      73              : 
      74            2 :     if (obj->create)
      75            1 :         return (obj->create (book));
      76              : 
      77            1 :     return nullptr;
      78              : }
      79              : 
      80          640 : void qof_object_book_begin (QofBook *book)
      81              : {
      82              :     GList *l;
      83              : 
      84          640 :     if (!book) return;
      85          640 :     ENTER (" ");
      86         8139 :     for (l = object_modules; l; l = l->next)
      87              :     {
      88         7499 :         QofObject *obj = static_cast<QofObject*>(l->data);
      89         7499 :         if (obj->book_begin)
      90         1979 :             obj->book_begin (book);
      91              :     }
      92              : 
      93              :     /* Remember this book for later */
      94          640 :     book_list = g_list_prepend (book_list, book);
      95          640 :     LEAVE (" ");
      96              : }
      97              : 
      98          499 : void qof_object_book_end (QofBook *book)
      99              : {
     100              :     GList *l;
     101              : 
     102          499 :     if (!book) return;
     103          499 :     ENTER (" ");
     104         5080 :     for (l = object_modules; l; l = l->next)
     105              :     {
     106         4581 :         QofObject *obj = static_cast<QofObject*>(l->data);
     107         4581 :         if (obj->book_end)
     108         3055 :             obj->book_end (book);
     109              :     }
     110              : 
     111              :     /* Remove it from the list */
     112          499 :     book_list = g_list_remove (book_list, book);
     113          499 :     LEAVE (" ");
     114              : }
     115              : 
     116              : gboolean
     117            4 : qof_object_is_dirty (const QofBook *book)
     118              : {
     119              :     GList *l;
     120              : 
     121            4 :     if (!book) return FALSE;
     122            6 :     for (l = object_modules; l; l = l->next)
     123              :     {
     124            4 :         QofObject *obj = static_cast<QofObject*>(l->data);
     125            4 :         if (obj->is_dirty)
     126              :         {
     127              :             QofCollection *col;
     128            4 :             col = qof_book_get_collection (book, obj->e_type);
     129            4 :             if (obj->is_dirty (col)) return TRUE;
     130              :         }
     131              :     }
     132            2 :     return FALSE;
     133              : }
     134              : 
     135              : void
     136            2 : qof_object_mark_clean (QofBook *book)
     137              : {
     138              :     GList *l;
     139              : 
     140            2 :     if (!book) return;
     141            5 :     for (l = object_modules; l; l = l->next)
     142              :     {
     143            3 :         QofObject *obj = static_cast<QofObject*>(l->data);
     144            3 :         if (obj->mark_clean)
     145              :         {
     146              :             QofCollection *col;
     147            3 :             col = qof_book_get_collection (book, obj->e_type);
     148            3 :             (obj->mark_clean) (col);
     149              :         }
     150              :     }
     151              : }
     152              : 
     153            7 : void qof_object_foreach_type (QofForeachTypeCB cb, gpointer user_data)
     154              : {
     155              :     GList *l;
     156              : 
     157            7 :     if (!cb) return;
     158              : 
     159           25 :     for (l = object_modules; l; l = l->next)
     160              :     {
     161           18 :         QofObject *obj = static_cast<QofObject*>(l->data);
     162           18 :         (cb) (obj, user_data);
     163              :     }
     164              : }
     165              : 
     166              : gboolean
     167            8 : qof_object_compliance (QofIdTypeConst type_name, gboolean warn)
     168              : {
     169              :     const QofObject *obj;
     170              : 
     171            8 :     obj = qof_object_lookup(type_name);
     172            8 :     if ((obj->create == nullptr) || (obj->foreach == nullptr))
     173              :     {
     174            6 :         if (warn)
     175              :         {
     176            3 :             PINFO (" Object type %s is not fully QOF compliant", obj->e_type);
     177              :         }
     178            6 :         return FALSE;
     179              :     }
     180            2 :     return TRUE;
     181              : }
     182              : 
     183              : 
     184              : void
     185          690 : qof_object_foreach (QofIdTypeConst type_name, QofBook *book,
     186              :                     QofInstanceForeachCB cb, gpointer user_data)
     187              : {
     188              :     QofCollection *col;
     189              :     const QofObject *obj;
     190              : 
     191          690 :     if (!book || !type_name)
     192              :     {
     193            6 :         return;
     194              :     }
     195          684 :     PINFO ("type=%s", type_name);
     196              : 
     197          684 :     obj = qof_object_lookup (type_name);
     198          684 :     if (!obj)
     199              :     {
     200            0 :         PERR ("No object of type %s", type_name);
     201            0 :         return;
     202              :     }
     203          684 :     col = qof_book_get_collection (book, obj->e_type);
     204          684 :     if (!col)
     205              :     {
     206            0 :         return;
     207              :     }
     208          684 :     if (obj->foreach)
     209              :     {
     210          684 :         obj->foreach (col, cb, user_data);
     211              :     }
     212          684 :     return;
     213              : }
     214              : 
     215              : static void
     216            6 : do_prepend (QofInstance *qof_p, gpointer list_p)
     217              : {
     218            6 :     GList **list = static_cast<GList**>(list_p);
     219            6 :     *list = g_list_prepend(*list, qof_p);
     220            6 : }
     221              : 
     222              : void
     223           37 : qof_object_foreach_sorted (QofIdTypeConst type_name, QofBook *book, QofInstanceForeachCB cb, gpointer user_data)
     224              : {
     225           37 :     GList *list = nullptr;
     226              :     GList *iter;
     227              : 
     228           37 :     qof_object_foreach(type_name, book, do_prepend, &list);
     229              : 
     230           37 :     list = g_list_sort(list, qof_instance_guid_compare);
     231              : 
     232           43 :     for (iter = list; iter; iter = iter->next)
     233              :     {
     234            6 :         cb(static_cast<QofInstance*>(iter->data), user_data);
     235              :     }
     236              : 
     237           37 :     g_list_free(list);
     238              : 
     239              :     // FIXME: Apparently this is a memory leak, as this g_list_free doesn't
     240              :     // free all of the allocated memory of g_list_append in do_append(). Why?!?
     241              :     // Does g_list_sort have special side-effects on the memory of the list?
     242              :     // Subsequently, I've changed the g_list_append into g_list_prepend, but
     243              :     // solely for performance reasons. To my surprise, this also makes the
     244              :     // dubious memory leak go away. But again why?!?
     245           37 : }
     246              : 
     247              : const char *
     248           13 : qof_object_printable (QofIdTypeConst type_name, gpointer obj)
     249              : {
     250              :     const QofObject *b_obj;
     251              : 
     252           13 :     if (!type_name || !obj) return nullptr;
     253              : 
     254            8 :     b_obj = qof_object_lookup (type_name);
     255            8 :     if (!b_obj) return nullptr;
     256              : 
     257            7 :     if (b_obj->printable)
     258            6 :         return (b_obj->printable (obj));
     259              : 
     260            1 :     return nullptr;
     261              : }
     262              : 
     263            4 : const char * qof_object_get_type_label (QofIdTypeConst type_name)
     264              : {
     265              :     const QofObject *obj;
     266              : 
     267            4 :     if (!type_name) return nullptr;
     268              : 
     269            3 :     obj = qof_object_lookup (type_name);
     270            3 :     if (!obj) return nullptr;
     271              : 
     272            2 :     return (obj->type_label);
     273              : }
     274              : 
     275              : /* INITIALIZATION and PRIVATE FUNCTIONS */
     276              : 
     277          131 : void qof_object_initialize (void)
     278              : {
     279          131 :     if (object_is_initialized) return;
     280          122 :     object_is_initialized = TRUE;
     281              : }
     282              : 
     283           56 : void qof_object_shutdown (void)
     284              : {
     285           56 :     g_return_if_fail (object_is_initialized == TRUE);
     286              : 
     287           56 :     g_list_free (object_modules);
     288           56 :     object_modules = nullptr;
     289           56 :     g_list_free (book_list);
     290           56 :     book_list = nullptr;
     291           56 :     object_is_initialized = FALSE;
     292              : }
     293              : 
     294              : /* Register new types of object objects.
     295              :  * Return TRUE if successful,
     296              :  * return FALSE if it fails, invalid arguments, or if the object
     297              :  * already exists
     298              :  */
     299         2141 : gboolean qof_object_register (const QofObject *object)
     300              : {
     301         2141 :     g_return_val_if_fail (object_is_initialized, FALSE);
     302              : 
     303         2141 :     if (!object) return FALSE;
     304         2139 :     g_return_val_if_fail (object->interface_version == QOF_OBJECT_VERSION, FALSE);
     305              : 
     306         2139 :     if (g_list_index (object_modules, (gpointer)object) == -1)
     307         2114 :         object_modules = g_list_prepend (object_modules, (gpointer)object);
     308              :     else
     309           25 :         return FALSE;
     310              : 
     311              :     /* Now initialize all the known books */
     312         2114 :     if (object->book_begin && book_list)
     313              :     {
     314              :         GList *node;
     315           74 :         for (node = book_list; node; node = node->next)
     316           40 :             object->book_begin (static_cast<QofBook*>(node->data));
     317              :     }
     318              : 
     319         2114 :     return TRUE;
     320              : }
     321              : 
     322          715 : const QofObject * qof_object_lookup (QofIdTypeConst name)
     323              : {
     324              :     GList *iter;
     325              :     const QofObject *obj;
     326              : 
     327          715 :     g_return_val_if_fail (object_is_initialized, nullptr);
     328              : 
     329          715 :     if (!name) return nullptr;
     330              : 
     331         7231 :     for (iter = object_modules; iter; iter = iter->next)
     332              :     {
     333         7226 :         obj = static_cast<QofObject*>(iter->data);
     334         7226 :         if (!g_strcmp0 (obj->e_type, name))
     335          709 :             return obj;
     336              :     }
     337            5 :     return nullptr;
     338              : }
     339              : 
     340              : /* ========================= END OF FILE =================== */
        

Generated by: LCOV version 2.0-1