LCOV - code coverage report
Current view: top level - libgnucash/engine - kvp-frame.cpp (source / functions) Coverage Total Hit
Test: gnucash.info Lines: 91.7 % 205 188
Test Date: 2025-02-07 16:25:45 Functions: 100.0 % 21 21
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /********************************************************************
       2                 :             :  * kvp_frame.cpp -- Implements a key-value frame system             *
       3                 :             :  * Copyright (C) 2000 Bill Gribble                                  *
       4                 :             :  * Copyright (C) 2001,2003 Linas Vepstas <linas@linas.org>          *
       5                 :             :  *                                                                  *
       6                 :             :  * This program is free software; you can redistribute it and/or    *
       7                 :             :  * modify it under the terms of the GNU General Public License as   *
       8                 :             :  * published by the Free Software Foundation; either version 2 of   *
       9                 :             :  * the License, or (at your option) any later version.              *
      10                 :             :  *                                                                  *
      11                 :             :  * This program is distributed in the hope that it will be useful,  *
      12                 :             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
      13                 :             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
      14                 :             :  * GNU General Public License for more details.                     *
      15                 :             :  *                                                                  *
      16                 :             :  * You should have received a copy of the GNU General Public License*
      17                 :             :  * along with this program; if not, contact:                        *
      18                 :             :  *                                                                  *
      19                 :             :  * Free Software Foundation           Voice:  +1-617-542-5942       *
      20                 :             :  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
      21                 :             :  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
      22                 :             :  *                                                                  *
      23                 :             :  ********************************************************************/
      24                 :             : #include <config.h>
      25                 :             : #include "qof.h"
      26                 :             : #include <glib.h>
      27                 :             : #include <stdarg.h>
      28                 :             : #include <stdio.h>
      29                 :             : #include <string.h>
      30                 :             : #include <cstdint>
      31                 :             : 
      32                 :             : #include "kvp-value.hpp"
      33                 :             : #include "kvp-frame.hpp"
      34                 :             : #include <typeinfo>
      35                 :             : #include <sstream>
      36                 :             : #include <algorithm>
      37                 :             : #include <vector>
      38                 :             : #include <numeric>
      39                 :             : 
      40                 :             : /* This static indicates the debugging module that this .o belongs to.  */
      41                 :             : static QofLogModule log_module = "qof.kvp";
      42                 :             : 
      43                 :        9025 : KvpFrameImpl::KvpFrameImpl(const KvpFrameImpl & rhs) noexcept
      44                 :             : {
      45                 :        9025 :     std::for_each(rhs.m_valuemap.begin(), rhs.m_valuemap.end(),
      46                 :       10645 :         [this](const map_type::value_type & a)
      47                 :             :         {
      48                 :       10645 :             auto key = qof_string_cache_insert(a.first);
      49                 :       10645 :             auto val = new KvpValueImpl(*a.second);
      50                 :       10645 :             this->m_valuemap.insert({key,val});
      51                 :       10645 :         }
      52                 :             :     );
      53                 :        9025 : }
      54                 :             : 
      55                 :      124037 : KvpFrameImpl::~KvpFrameImpl() noexcept
      56                 :             : {
      57                 :      124037 :     std::for_each(m_valuemap.begin(), m_valuemap.end(),
      58                 :       24696 :                  [](const map_type::value_type &a){
      59                 :       24696 :                       qof_string_cache_remove(a.first);
      60                 :       24696 :                       delete a.second;
      61                 :       24696 :                   }
      62                 :             :         );
      63                 :      124037 :     m_valuemap.clear();
      64                 :      124037 : }
      65                 :             : 
      66                 :             : KvpFrame *
      67                 :      304124 : KvpFrame::get_child_frame_or_nullptr (Path const & path) noexcept
      68                 :             : {
      69                 :      304124 :     if (!path.size ())
      70                 :      291988 :         return this;
      71                 :       12136 :     auto key = path.front ();
      72                 :       12136 :     auto map_iter = m_valuemap.find (key.c_str ());
      73                 :       12136 :     if (map_iter == m_valuemap.end ())
      74                 :       10804 :         return nullptr;
      75                 :        1332 :     auto child = map_iter->second->get <KvpFrame *> ();
      76                 :        1332 :     if (!child)
      77                 :           6 :         return nullptr;
      78                 :        1326 :     Path send;
      79                 :        1326 :     std::copy (path.begin () + 1, path.end (), std::back_inserter (send));
      80                 :        1326 :     return child->get_child_frame_or_nullptr (send);
      81                 :       12136 : }
      82                 :             : 
      83                 :             : KvpFrame *
      84                 :       20522 : KvpFrame::get_child_frame_or_create (Path const & path) noexcept
      85                 :             : {
      86                 :       20522 :     if (!path.size ())
      87                 :       19880 :         return this;
      88                 :         642 :     auto key = path.front ();
      89                 :         642 :     auto spot = m_valuemap.find (key.c_str ());
      90                 :         642 :     if (spot == m_valuemap.end () || spot->second->get_type () != KvpValue::Type::FRAME)
      91                 :        1053 :         delete set_impl (key.c_str (), new KvpValue {new KvpFrame});
      92                 :         642 :     Path send;
      93                 :         642 :     std::copy (path.begin () + 1, path.end (), std::back_inserter (send));
      94                 :         642 :     auto child_val = m_valuemap.at (key.c_str ());
      95                 :         642 :     auto child = child_val->get <KvpFrame *> ();
      96                 :         642 :     return child->get_child_frame_or_create (send);
      97                 :         642 : }
      98                 :             : 
      99                 :             : 
     100                 :             : KvpValue *
     101                 :       23454 : KvpFrame::set_impl (std::string const & key, KvpValue * value) noexcept
     102                 :             : {
     103                 :       23454 :     KvpValue * ret {};
     104                 :       23454 :     auto spot = m_valuemap.find (key.c_str ());
     105                 :       23454 :     if (spot != m_valuemap.end ())
     106                 :             :     {
     107                 :         263 :         qof_string_cache_remove (spot->first);
     108                 :         263 :         ret = spot->second;
     109                 :         263 :         m_valuemap.erase (spot);
     110                 :             :     }
     111                 :       23454 :     if (value)
     112                 :             :     {
     113                 :       19790 :         auto cachedkey = static_cast <char const *> (qof_string_cache_insert (key.c_str ()));
     114                 :       19790 :         m_valuemap.emplace (cachedkey, value);
     115                 :             :     }
     116                 :       23454 :     return ret;
     117                 :             : }
     118                 :             : 
     119                 :             : KvpValue *
     120                 :        3230 : KvpFrameImpl::set (Path path, KvpValue* value) noexcept
     121                 :             : {
     122                 :        3230 :     if (path.empty())
     123                 :           0 :         return nullptr;
     124                 :        3230 :     auto key = path.back ();
     125                 :        3230 :     path.pop_back ();
     126                 :        3230 :     auto target = get_child_frame_or_nullptr (path);
     127                 :        3230 :     if (!target)
     128                 :           7 :         return nullptr;
     129                 :        3223 :     return target->set_impl (key, value);
     130                 :        3230 : }
     131                 :             : 
     132                 :             : KvpValue *
     133                 :       19880 : KvpFrameImpl::set_path (Path path, KvpValue* value) noexcept
     134                 :             : {
     135                 :       19880 :     auto key = path.back();
     136                 :       19880 :     path.pop_back();
     137                 :       19880 :     auto target = get_child_frame_or_create (path);
     138                 :       19880 :     if (!target)
     139                 :           0 :         return nullptr;
     140                 :       19880 :     return target->set_impl (key, value);
     141                 :       19880 : }
     142                 :             : 
     143                 :             : KvpValue *
     144                 :      299568 : KvpFrameImpl::get_slot (Path path) noexcept
     145                 :             : {
     146                 :      299568 :     auto key = path.back();
     147                 :      299568 :     path.pop_back();
     148                 :      299568 :     auto target = get_child_frame_or_nullptr (path);
     149                 :      299568 :     if (!target)
     150                 :       10803 :         return nullptr;
     151                 :      288765 :     auto spot = target->m_valuemap.find (key.c_str ());
     152                 :      288765 :     if (spot != target->m_valuemap.end ())
     153                 :        2897 :         return spot->second;
     154                 :      285868 :     return nullptr;
     155                 :      299568 : }
     156                 :             : 
     157                 :             : std::string
     158                 :          22 : KvpFrameImpl::to_string() const noexcept
     159                 :             : {
     160                 :          44 :     return to_string("");
     161                 :             : }
     162                 :             : 
     163                 :             : std::string
     164                 :          39 : KvpFrameImpl::to_string(std::string const & prefix) const noexcept
     165                 :             : {
     166                 :          39 :     if (!m_valuemap.size())
     167                 :           0 :         return prefix;
     168                 :          39 :     std::ostringstream ret;
     169                 :          39 :     std::for_each(m_valuemap.begin(), m_valuemap.end(),
     170                 :         141 :         [&ret,&prefix](const map_type::value_type &a)
     171                 :             :         {
     172                 :         141 :             std::string new_prefix {prefix};
     173                 :         141 :             if (a.first)
     174                 :             :             {
     175                 :         141 :                 new_prefix += a.first;
     176                 :         141 :                 new_prefix += "/";
     177                 :             :             }
     178                 :         141 :             if (a.second)
     179                 :         141 :                 ret << a.second->to_string(new_prefix) << "\n";
     180                 :             :             else
     181                 :           0 :                 ret << new_prefix << "(null)\n";
     182                 :         141 :         }
     183                 :             :     );
     184                 :          39 :     return ret.str();
     185                 :          39 : }
     186                 :             : 
     187                 :             : std::vector<std::string>
     188                 :          16 : KvpFrameImpl::get_keys() const noexcept
     189                 :             : {
     190                 :          16 :     std::vector<std::string> ret;
     191                 :          16 :     ret.reserve (m_valuemap.size());
     192                 :          16 :     std::for_each(m_valuemap.begin(), m_valuemap.end(),
     193                 :          11 :         [&ret](const KvpFrameImpl::map_type::value_type &a)
     194                 :             :         {
     195                 :          22 :             ret.push_back(a.first);
     196                 :          11 :         }
     197                 :             :     );
     198                 :          16 :     return ret;
     199                 :             : }
     200                 :             : 
     201                 :        1117 : int compare(const KvpFrameImpl * one, const KvpFrameImpl * two) noexcept
     202                 :             : {
     203                 :        1117 :     if (one && !two) return 1;
     204                 :        1117 :     if (!one && two) return -1;
     205                 :        1117 :     if (!one && !two) return 0;
     206                 :        1117 :     return compare(*one, *two);
     207                 :             : }
     208                 :             : 
     209                 :             : /**
     210                 :             :  * If the first KvpFrameImpl has an item that the second does not, 1 is returned.
     211                 :             :  * The first item within the two KvpFrameImpl that is not similar, that comparison is returned.
     212                 :             :  * If all the items within the first KvpFrameImpl match items within the second, but the
     213                 :             :  *   second has more elements, -1 is returned.
     214                 :             :  * Otherwise, 0 is returned.
     215                 :             :  */
     216                 :        1117 : int compare(const KvpFrameImpl & one, const KvpFrameImpl & two) noexcept
     217                 :             : {
     218                 :        5080 :     for (const auto & a : one.m_valuemap)
     219                 :             :     {
     220                 :        3966 :         auto otherspot = two.m_valuemap.find(a.first);
     221                 :        3966 :         if (otherspot == two.m_valuemap.end())
     222                 :             :         {
     223                 :           0 :             return 1;
     224                 :             :         }
     225                 :        3966 :         auto comparison = compare(a.second,otherspot->second);
     226                 :             : 
     227                 :        3966 :         if (comparison != 0)
     228                 :           3 :             return comparison;
     229                 :             :     }
     230                 :             : 
     231                 :        1114 :     if (one.m_valuemap.size() < two.m_valuemap.size())
     232                 :           0 :         return -1;
     233                 :        1114 :     return 0;
     234                 :             : }
     235                 :             : 
     236                 :             : void
     237                 :      290180 : gvalue_from_kvp_value (const KvpValue *kval, GValue* val)
     238                 :             : {
     239                 :      290180 :     if (kval == NULL) return;
     240                 :        2642 :     g_value_unset(val);
     241                 :             : 
     242                 :        2642 :     switch (kval->get_type())
     243                 :             :     {
     244                 :         868 :         case KvpValue::Type::INT64:
     245                 :         868 :             g_value_init (val, G_TYPE_INT64);
     246                 :         868 :             g_value_set_int64 (val, kval->get<int64_t>());
     247                 :         868 :             break;
     248                 :           3 :         case KvpValue::Type::DOUBLE:
     249                 :           3 :             g_value_init (val, G_TYPE_DOUBLE);
     250                 :           3 :             g_value_set_double (val, kval->get<double>());
     251                 :           3 :             break;
     252                 :          75 :         case KvpValue::Type::NUMERIC:
     253                 :          75 :             g_value_init (val, GNC_TYPE_NUMERIC);
     254                 :          75 :             g_value_set_static_boxed (val, kval->get_ptr<gnc_numeric>());
     255                 :          75 :             break;
     256                 :        1045 :         case KvpValue::Type::STRING:
     257                 :        1045 :             g_value_init (val, G_TYPE_STRING);
     258                 :        1045 :             g_value_set_static_string (val, kval->get<const char*>());
     259                 :        1045 :             break;
     260                 :         568 :         case KvpValue::Type::GUID:
     261                 :         568 :             g_value_init (val, GNC_TYPE_GUID);
     262                 :         568 :             g_value_set_static_boxed (val, kval->get<GncGUID*>());
     263                 :         568 :             break;
     264                 :          83 :         case KvpValue::Type::TIME64:
     265                 :          83 :             g_value_init (val, GNC_TYPE_TIME64);
     266                 :          83 :             g_value_set_boxed (val, kval->get_ptr<Time64>());
     267                 :          83 :             break;
     268                 :           0 :         case KvpValue::Type::GDATE:
     269                 :           0 :             g_value_init (val, G_TYPE_DATE);
     270                 :           0 :             g_value_set_static_boxed (val, kval->get_ptr<GDate>());
     271                 :           0 :             break;
     272                 :           0 :         default:
     273                 :             : /* No transfer outside of QofInstance-derived classes! */
     274                 :           0 :             PWARN ("Error! Invalid attempt to transfer Kvp type %d", kval->get_type());
     275                 :           0 :             break;
     276                 :             :     }
     277                 :             : }
     278                 :             : 
     279                 :             : KvpValue*
     280                 :        5723 : kvp_value_from_gvalue (const GValue *gval)
     281                 :             : {
     282                 :        5723 :     KvpValue *val = NULL;
     283                 :             :     GType type;
     284                 :        5723 :     if (gval == NULL)
     285                 :        1846 :         return NULL;
     286                 :        3877 :     type = G_VALUE_TYPE (gval);
     287                 :        3877 :     g_return_val_if_fail (G_VALUE_TYPE (gval), NULL);
     288                 :             : 
     289                 :        3877 :     if (type == G_TYPE_INT64)
     290                 :         121 :         val = new KvpValue(g_value_get_int64 (gval));
     291                 :        3756 :     else if (type == G_TYPE_DOUBLE)
     292                 :           3 :         val = new KvpValue(g_value_get_double (gval));
     293                 :        3753 :     else if (type == G_TYPE_BOOLEAN)
     294                 :             :     {
     295                 :           0 :         auto bval = g_value_get_boolean(gval);
     296                 :           0 :         if (bval)
     297                 :           0 :             val = new KvpValue(g_strdup("true"));
     298                 :             :     }
     299                 :        3753 :     else if (type == GNC_TYPE_NUMERIC)
     300                 :         413 :         val = new KvpValue(*(gnc_numeric*)g_value_get_boxed (gval));
     301                 :        3340 :     else if (type == G_TYPE_STRING)
     302                 :             :     {
     303                 :         931 :         auto string = g_value_get_string(gval);
     304                 :         931 :         if (string != nullptr)
     305                 :        1800 :             val = new KvpValue(g_strdup(string));
     306                 :             :     }
     307                 :        2409 :     else if (type == GNC_TYPE_GUID)
     308                 :             :     {
     309                 :         197 :         auto boxed = g_value_get_boxed(gval);
     310                 :         197 :         if (boxed != nullptr)
     311                 :         189 :             val = new KvpValue(guid_copy(static_cast<GncGUID*>(boxed)));
     312                 :             :     }
     313                 :        2212 :     else if (type == GNC_TYPE_TIME64)
     314                 :          66 :         val = new KvpValue(*(Time64*)g_value_get_boxed (gval));
     315                 :        2146 :     else if (type == G_TYPE_DATE)
     316                 :        2146 :         val = new KvpValue(*(GDate*)g_value_get_boxed (gval));
     317                 :             :     else
     318                 :           0 :         PWARN ("Error! Don't know how to make a KvpValue from a %s",
     319                 :             :                G_VALUE_TYPE_NAME (gval));
     320                 :             : 
     321                 :        3877 :     return val;
     322                 :             : }
     323                 :             : 
     324                 :             : void
     325                 :           8 : KvpFrame::flatten_kvp_impl(std::vector <std::string> path, std::vector <KvpEntry> & entries) const noexcept
     326                 :             : {
     327                 :          22 :     for (auto const & entry : m_valuemap)
     328                 :             :     {
     329                 :          14 :         std::vector<std::string> new_path {path};
     330                 :          14 :         new_path.push_back("/");
     331                 :          14 :         if (entry.second->get_type() == KvpValue::Type::FRAME)
     332                 :             :         {
     333                 :           7 :             new_path.push_back(entry.first);
     334                 :           7 :             entry.second->get<KvpFrame*>()->flatten_kvp_impl(new_path, entries);
     335                 :             :         }
     336                 :             :         else
     337                 :             :         {
     338                 :           7 :             new_path.emplace_back (entry.first);
     339                 :           7 :             entries.emplace_back (new_path, entry.second);
     340                 :             :         }
     341                 :          14 :     }
     342                 :           8 : }
     343                 :             : 
     344                 :             : std::vector <KvpEntry>
     345                 :           1 : KvpFrame::flatten_kvp(void) const noexcept
     346                 :             : {
     347                 :           1 :     std::vector <KvpEntry> ret;
     348                 :           1 :     flatten_kvp_impl({}, ret);
     349                 :           1 :     return ret;
     350                 :             : }
        

Generated by: LCOV version 2.0-1