2005-11-07 09:45:58 -06:00
|
|
|
/********************************************************************
|
2014-09-19 15:35:03 -05:00
|
|
|
* kvp_frame.cpp -- Implements a key-value frame system *
|
2005-11-07 09:45:58 -06:00
|
|
|
* Copyright (C) 2000 Bill Gribble *
|
|
|
|
* Copyright (C) 2001,2003 Linas Vepstas <linas@linas.org> *
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or *
|
|
|
|
* modify it under the terms of the GNU General Public License as *
|
|
|
|
* published by the Free Software Foundation; either version 2 of *
|
|
|
|
* the License, or (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
* This program is distributed in the hope that it will be useful, *
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
* GNU General Public License for more details. *
|
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License*
|
|
|
|
* along with this program; if not, contact: *
|
|
|
|
* *
|
|
|
|
* Free Software Foundation Voice: +1-617-542-5942 *
|
2005-11-16 23:35:02 -06:00
|
|
|
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
|
|
|
|
* Boston, MA 02110-1301, USA gnu@gnu.org *
|
2005-11-07 09:45:58 -06:00
|
|
|
* *
|
|
|
|
********************************************************************/
|
|
|
|
|
2014-04-25 15:41:11 -05:00
|
|
|
extern "C"
|
|
|
|
{
|
2005-11-07 09:45:58 -06:00
|
|
|
#include "config.h"
|
2014-09-19 15:35:03 -05:00
|
|
|
#include "qof.h"
|
2005-11-07 09:45:58 -06:00
|
|
|
#include <glib.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
2014-04-25 15:41:11 -05:00
|
|
|
}
|
|
|
|
|
2014-09-19 15:35:03 -05:00
|
|
|
#include "kvp-value.hpp"
|
2014-10-03 21:05:37 -05:00
|
|
|
#include "kvp_frame.hpp"
|
|
|
|
#include <typeinfo>
|
|
|
|
#include <sstream>
|
|
|
|
#include <algorithm>
|
|
|
|
#include <vector>
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2015-06-27 17:39:54 -05:00
|
|
|
/* This static indicates the debugging module that this .o belongs to. */
|
|
|
|
static QofLogModule log_module = "qof.kvp";
|
|
|
|
|
2015-06-21 17:10:33 -05:00
|
|
|
static const char delim = '/';
|
|
|
|
|
2014-10-03 21:05:37 -05:00
|
|
|
KvpFrameImpl::KvpFrameImpl(const KvpFrameImpl & rhs) noexcept
|
|
|
|
{
|
|
|
|
std::for_each(rhs.m_valuemap.begin(), rhs.m_valuemap.end(),
|
|
|
|
[this](const map_type::value_type & a)
|
|
|
|
{
|
|
|
|
auto key = static_cast<char *>(qof_string_cache_insert(a.first));
|
|
|
|
auto val = new KvpValueImpl(*a.second);
|
|
|
|
this->m_valuemap.insert({key,val});
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2015-07-06 15:55:13 -05:00
|
|
|
KvpFrameImpl::~KvpFrameImpl() noexcept
|
|
|
|
{
|
|
|
|
std::for_each(m_valuemap.begin(), m_valuemap.end(),
|
|
|
|
[](const map_type::value_type &a){
|
|
|
|
qof_string_cache_remove(a.first);
|
|
|
|
delete a.second;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
m_valuemap.clear();
|
|
|
|
}
|
|
|
|
|
2015-06-21 17:10:33 -05:00
|
|
|
static inline Path
|
|
|
|
make_vector(std::string key)
|
|
|
|
{
|
|
|
|
Path path;
|
|
|
|
for (auto length = key.find(delim); length != std::string::npos;)
|
|
|
|
{
|
2015-07-23 00:05:13 -05:00
|
|
|
if (length != 0)
|
|
|
|
path.push_back(key.substr(0, length));
|
2015-06-21 17:10:33 -05:00
|
|
|
key = key.substr(length + 1);
|
|
|
|
length = key.find(delim);
|
|
|
|
}
|
|
|
|
path.push_back(key);
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2015-06-18 15:55:55 -05:00
|
|
|
KvpValue*
|
|
|
|
KvpFrameImpl::set(const char* key, KvpValue* value) noexcept
|
2014-10-03 21:05:37 -05:00
|
|
|
{
|
|
|
|
if (!key) return nullptr;
|
2015-06-21 17:10:33 -05:00
|
|
|
if (strchr(key, delim))
|
|
|
|
return set(make_vector(key), value);
|
2015-06-18 15:55:55 -05:00
|
|
|
KvpValue* ret {nullptr};
|
2015-06-21 17:10:33 -05:00
|
|
|
auto spot = m_valuemap.find(key);
|
2014-10-03 21:05:37 -05:00
|
|
|
if (spot != m_valuemap.end())
|
|
|
|
{
|
|
|
|
qof_string_cache_remove(spot->first);
|
|
|
|
ret = spot->second;
|
|
|
|
m_valuemap.erase(spot);
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2014-10-03 21:05:37 -05:00
|
|
|
if (value)
|
|
|
|
{
|
2015-06-21 17:10:33 -05:00
|
|
|
auto cachedkey =
|
|
|
|
static_cast<const char *>(qof_string_cache_insert(key));
|
2014-10-03 21:05:37 -05:00
|
|
|
m_valuemap.insert({cachedkey,value});
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2014-10-03 21:05:37 -05:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2015-06-18 15:55:55 -05:00
|
|
|
static inline KvpFrameImpl*
|
|
|
|
walk_path_or_nullptr(const KvpFrameImpl* frame, Path& path)
|
|
|
|
{
|
|
|
|
KvpFrameImpl* cur_frame = const_cast<KvpFrameImpl*>(frame);
|
|
|
|
for(auto key:path)
|
|
|
|
{
|
2015-06-21 17:10:33 -05:00
|
|
|
auto slot = cur_frame->get_slot(key.c_str());
|
2015-06-27 17:39:54 -05:00
|
|
|
if (slot == nullptr || slot->get_type() != KvpValue::Type::FRAME)
|
2015-06-18 15:55:55 -05:00
|
|
|
return nullptr;
|
|
|
|
cur_frame = slot->get<KvpFrame*>();
|
|
|
|
}
|
|
|
|
return cur_frame;
|
|
|
|
}
|
|
|
|
|
|
|
|
KvpValue*
|
|
|
|
KvpFrameImpl::set(Path path, KvpValue* value) noexcept
|
|
|
|
{
|
2015-06-21 17:10:33 -05:00
|
|
|
auto last_key = path.back();
|
2015-06-18 15:55:55 -05:00
|
|
|
path.pop_back();
|
|
|
|
auto cur_frame = walk_path_or_nullptr(this, path);
|
|
|
|
if (cur_frame == nullptr)
|
|
|
|
return nullptr;
|
2015-06-21 17:10:33 -05:00
|
|
|
if (last_key.find(delim) != std::string::npos)
|
|
|
|
return set(make_vector(last_key), value);
|
|
|
|
return cur_frame->set(last_key.c_str(), value);
|
2015-06-18 15:55:55 -05:00
|
|
|
}
|
|
|
|
|
2015-06-21 17:10:33 -05:00
|
|
|
static inline KvpFrameImpl*
|
|
|
|
walk_path_and_create(KvpFrameImpl* frame, Path path)
|
2015-06-18 15:55:55 -05:00
|
|
|
{
|
2015-06-21 17:10:33 -05:00
|
|
|
for(auto key:path)
|
2015-06-18 15:55:55 -05:00
|
|
|
{
|
2015-06-21 17:10:33 -05:00
|
|
|
if (key.find(delim) != std::string::npos)
|
|
|
|
{
|
|
|
|
frame = walk_path_and_create(frame, make_vector(key));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
auto slot = frame->get_slot(key.c_str());
|
2015-06-27 17:39:54 -05:00
|
|
|
if (slot == nullptr || slot->get_type() != KvpValue::Type::FRAME)
|
2015-06-18 15:55:55 -05:00
|
|
|
{
|
|
|
|
auto new_frame = new KvpFrame;
|
2015-06-21 17:10:33 -05:00
|
|
|
delete frame->set(key.c_str(), new KvpValue{new_frame});
|
|
|
|
frame = new_frame;
|
2015-06-18 15:55:55 -05:00
|
|
|
continue;
|
|
|
|
}
|
2015-06-21 17:10:33 -05:00
|
|
|
frame = slot->get<KvpFrame*>();
|
2015-06-18 15:55:55 -05:00
|
|
|
}
|
2015-06-21 17:10:33 -05:00
|
|
|
return frame;
|
|
|
|
}
|
|
|
|
|
2015-06-26 14:24:34 -05:00
|
|
|
KvpValue*
|
|
|
|
KvpFrameImpl::set_path(const char* path, KvpValue* value) noexcept
|
|
|
|
{
|
|
|
|
return set_path(make_vector(path), value);
|
|
|
|
}
|
|
|
|
|
2015-06-21 17:10:33 -05:00
|
|
|
KvpValue*
|
|
|
|
KvpFrameImpl::set_path(Path path, KvpValue* value) noexcept
|
|
|
|
{
|
|
|
|
auto cur_frame = this;
|
|
|
|
auto last_key = path.back();
|
|
|
|
path.pop_back();
|
|
|
|
cur_frame = walk_path_and_create(const_cast<KvpFrame*>(this), path);
|
|
|
|
if (last_key.find(delim) != std::string::npos)
|
|
|
|
return set_path(make_vector(last_key), value);
|
|
|
|
return cur_frame->set(last_key.c_str(), value);
|
2015-06-18 15:55:55 -05:00
|
|
|
}
|
|
|
|
|
2014-10-03 21:05:37 -05:00
|
|
|
std::string
|
|
|
|
KvpFrameImpl::to_string() const noexcept
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-10-03 21:05:37 -05:00
|
|
|
std::ostringstream ret;
|
|
|
|
ret << "{\n";
|
|
|
|
|
|
|
|
std::for_each(m_valuemap.begin(), m_valuemap.end(),
|
|
|
|
[this,&ret](const map_type::value_type &a)
|
|
|
|
{
|
|
|
|
ret << " ";
|
|
|
|
if (a.first)
|
|
|
|
ret << a.first;
|
|
|
|
ret << " => ";
|
|
|
|
if (a.second)
|
|
|
|
ret << a.second->to_string();
|
|
|
|
ret << ",\n";
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
ret << "}\n";
|
|
|
|
return ret.str();
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2014-10-03 21:05:37 -05:00
|
|
|
std::vector<std::string>
|
|
|
|
KvpFrameImpl::get_keys() const noexcept
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-10-03 21:05:37 -05:00
|
|
|
std::vector<std::string> ret;
|
|
|
|
std::for_each(m_valuemap.begin(), m_valuemap.end(),
|
|
|
|
[&ret](const KvpFrameImpl::map_type::value_type &a)
|
|
|
|
{
|
|
|
|
ret.push_back(a.first);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
return ret;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2014-10-03 21:05:37 -05:00
|
|
|
void
|
2015-06-09 16:46:09 -05:00
|
|
|
KvpFrameImpl::for_each_slot(void (*proc)(const char *key, KvpValue *value,
|
|
|
|
void * data),
|
|
|
|
void *data) const noexcept
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-10-03 21:05:37 -05:00
|
|
|
if (!proc) return;
|
|
|
|
std::for_each (m_valuemap.begin(), m_valuemap.end(),
|
|
|
|
[proc,data](const KvpFrameImpl::map_type::value_type & a)
|
|
|
|
{
|
|
|
|
proc (a.first, a.second, data);
|
|
|
|
}
|
|
|
|
);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2014-10-03 21:05:37 -05:00
|
|
|
KvpValueImpl *
|
|
|
|
KvpFrameImpl::get_slot(const char * key) const noexcept
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2015-06-21 17:10:33 -05:00
|
|
|
if (!key) return nullptr;
|
|
|
|
if (strchr(key, delim))
|
|
|
|
return get_slot(make_vector(key));
|
2014-10-03 21:05:37 -05:00
|
|
|
auto spot = m_valuemap.find(key);
|
|
|
|
if (spot == m_valuemap.end())
|
|
|
|
return nullptr;
|
|
|
|
return spot->second;
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2015-06-18 15:55:55 -05:00
|
|
|
KvpValueImpl *
|
|
|
|
KvpFrameImpl::get_slot(Path path) const noexcept
|
|
|
|
{
|
2015-06-21 17:10:33 -05:00
|
|
|
auto last_key = path.back();
|
2015-06-18 15:55:55 -05:00
|
|
|
path.pop_back();
|
|
|
|
auto cur_frame = walk_path_or_nullptr(this, path);
|
|
|
|
if (cur_frame == nullptr)
|
|
|
|
return nullptr;
|
2015-06-21 17:10:33 -05:00
|
|
|
if (last_key.find(delim) != std::string::npos)
|
|
|
|
return get_slot(make_vector(last_key));
|
|
|
|
return cur_frame->get_slot(last_key.c_str());
|
2015-06-18 15:55:55 -05:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2014-10-03 21:05:37 -05:00
|
|
|
int compare(const KvpFrameImpl * one, const KvpFrameImpl * two) noexcept
|
|
|
|
{
|
|
|
|
if (one && !two) return 1;
|
|
|
|
if (!one && two) return -1;
|
|
|
|
if (!one && !two) return 0;
|
|
|
|
return compare(*one, *two);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2014-10-03 21:05:37 -05:00
|
|
|
/**
|
|
|
|
* If the first KvpFrameImpl has an item that the second does not, 1 is returned.
|
|
|
|
* The first item within the two KvpFrameImpl that is not similar, that comparison is returned.
|
|
|
|
* If all the items within the first KvpFrameImpl match items within the second, but the
|
|
|
|
* second has more elements, -1 is returned.
|
|
|
|
* Otherwise, 0 is returned.
|
|
|
|
*/
|
|
|
|
int compare(const KvpFrameImpl & one, const KvpFrameImpl & two) noexcept
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-10-03 21:05:37 -05:00
|
|
|
for (const auto & a : one.m_valuemap)
|
|
|
|
{
|
|
|
|
auto otherspot = two.m_valuemap.find(a.first);
|
|
|
|
if (otherspot == two.m_valuemap.end())
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
auto comparison = compare(a.second,otherspot->second);
|
|
|
|
|
|
|
|
if (comparison != 0)
|
|
|
|
return comparison;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (one.m_valuemap.size() < two.m_valuemap.size())
|
|
|
|
return -1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2014-05-07 08:37:14 -05:00
|
|
|
static void
|
|
|
|
gvalue_list_from_kvp_value (KvpValue *kval, gpointer pList)
|
|
|
|
{
|
|
|
|
GList **gvlist = NULL;
|
|
|
|
GValue *gval = gvalue_from_kvp_value (kval);
|
|
|
|
gvlist = (GList**)pList;
|
|
|
|
if (G_VALUE_TYPE (gval))
|
2015-05-07 18:12:54 -05:00
|
|
|
*gvlist = g_list_prepend (*gvlist, gval);
|
2014-05-07 08:37:14 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
kvp_value_list_from_gvalue (GValue *gval, gpointer pList)
|
|
|
|
{
|
|
|
|
GList **kvplist = (GList**)pList;
|
|
|
|
KvpValue *kvp;
|
|
|
|
if (!(gval && G_VALUE_TYPE (gval)))
|
2015-05-07 18:12:54 -05:00
|
|
|
return;
|
2014-05-07 08:37:14 -05:00
|
|
|
kvp = kvp_value_from_gvalue (gval);
|
|
|
|
*kvplist = g_list_prepend (*kvplist, kvp);
|
|
|
|
}
|
|
|
|
|
2015-06-09 16:42:39 -05:00
|
|
|
GValue*
|
|
|
|
gvalue_from_kvp_value (const KvpValue *kval)
|
2014-05-07 08:37:14 -05:00
|
|
|
{
|
|
|
|
GValue *val;
|
|
|
|
gnc_numeric num;
|
|
|
|
Timespec tm;
|
|
|
|
GDate gdate;
|
|
|
|
|
|
|
|
if (kval == NULL) return NULL;
|
|
|
|
val = g_slice_new0 (GValue);
|
|
|
|
|
2015-06-27 17:39:54 -05:00
|
|
|
switch (kval->get_type())
|
2014-05-07 08:37:14 -05:00
|
|
|
{
|
2015-06-27 17:39:54 -05:00
|
|
|
case KvpValue::Type::INT64:
|
2015-05-07 18:12:54 -05:00
|
|
|
g_value_init (val, G_TYPE_INT64);
|
2015-06-30 14:04:34 -05:00
|
|
|
g_value_set_int64 (val, kval->get<int64_t>());
|
2015-05-07 18:12:54 -05:00
|
|
|
break;
|
2015-06-27 17:39:54 -05:00
|
|
|
case KvpValue::Type::DOUBLE:
|
2015-05-07 18:12:54 -05:00
|
|
|
g_value_init (val, G_TYPE_DOUBLE);
|
2015-06-30 14:04:34 -05:00
|
|
|
g_value_set_double (val, kval->get<double>());
|
2015-05-07 18:12:54 -05:00
|
|
|
break;
|
2015-06-27 17:39:54 -05:00
|
|
|
case KvpValue::Type::NUMERIC:
|
2015-05-07 18:12:54 -05:00
|
|
|
g_value_init (val, GNC_TYPE_NUMERIC);
|
2015-06-30 14:04:34 -05:00
|
|
|
num = kval->get<gnc_numeric>();
|
2015-05-07 18:12:54 -05:00
|
|
|
g_value_set_boxed (val, &num);
|
|
|
|
break;
|
2015-06-27 17:39:54 -05:00
|
|
|
case KvpValue::Type::STRING:
|
2015-05-07 18:12:54 -05:00
|
|
|
g_value_init (val, G_TYPE_STRING);
|
2015-06-30 14:04:34 -05:00
|
|
|
g_value_set_string (val, kval->get<const char*>());
|
2015-05-07 18:12:54 -05:00
|
|
|
break;
|
2015-06-27 17:39:54 -05:00
|
|
|
case KvpValue::Type::GUID:
|
2015-05-07 18:12:54 -05:00
|
|
|
g_value_init (val, GNC_TYPE_GUID);
|
2015-06-30 14:04:34 -05:00
|
|
|
g_value_set_boxed (val, kval->get<GncGUID*>());
|
2015-05-07 18:12:54 -05:00
|
|
|
break;
|
2015-06-27 17:39:54 -05:00
|
|
|
case KvpValue::Type::TIMESPEC:
|
2015-05-07 18:12:54 -05:00
|
|
|
g_value_init (val, GNC_TYPE_TIMESPEC);
|
2015-06-30 14:04:34 -05:00
|
|
|
tm = kval->get<Timespec>();
|
2015-05-07 18:12:54 -05:00
|
|
|
g_value_set_boxed (val, &tm);
|
|
|
|
break;
|
2015-06-27 17:39:54 -05:00
|
|
|
case KvpValue::Type::GDATE:
|
2015-05-07 18:12:54 -05:00
|
|
|
g_value_init (val, G_TYPE_DATE);
|
2015-06-30 14:04:34 -05:00
|
|
|
gdate = kval->get<GDate>();
|
2015-05-07 18:12:54 -05:00
|
|
|
g_value_set_boxed (val, &gdate);
|
|
|
|
break;
|
2015-06-27 17:39:54 -05:00
|
|
|
case KvpValue::Type::GLIST:
|
2015-05-07 18:12:54 -05:00
|
|
|
{
|
|
|
|
GList *gvalue_list = NULL;
|
2015-06-30 14:04:34 -05:00
|
|
|
GList *kvp_list = kval->get<GList*>();
|
|
|
|
g_list_foreach (kvp_list, (GFunc)gvalue_list_from_kvp_value,
|
|
|
|
&gvalue_list);
|
2015-05-07 18:12:54 -05:00
|
|
|
g_value_init (val, GNC_TYPE_VALUE_LIST);
|
|
|
|
gvalue_list = g_list_reverse (gvalue_list);
|
|
|
|
g_value_set_boxed (val, gvalue_list);
|
|
|
|
break;
|
|
|
|
}
|
2014-05-07 08:37:14 -05:00
|
|
|
/* No transfer of KVP frames outside of QofInstance-derived classes! */
|
2015-06-27 17:39:54 -05:00
|
|
|
case KvpValue::Type::FRAME:
|
2015-05-07 18:12:54 -05:00
|
|
|
PWARN ("Error! Attempt to transfer KvpFrame!");
|
|
|
|
default:
|
|
|
|
PWARN ("Error! Invalid KVP Transfer Request!");
|
|
|
|
g_slice_free (GValue, val);
|
|
|
|
val = NULL;
|
|
|
|
break;
|
2014-05-07 08:37:14 -05:00
|
|
|
}
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
KvpValue*
|
|
|
|
kvp_value_from_gvalue (const GValue *gval)
|
|
|
|
{
|
|
|
|
KvpValue *val = NULL;
|
2015-05-07 18:12:54 -05:00
|
|
|
GType type;
|
|
|
|
if (gval == NULL)
|
|
|
|
return NULL;
|
|
|
|
type = G_VALUE_TYPE (gval);
|
2014-05-07 08:37:14 -05:00
|
|
|
g_return_val_if_fail (G_VALUE_TYPE (gval), NULL);
|
|
|
|
|
|
|
|
if (type == G_TYPE_INT64)
|
2015-06-30 14:04:34 -05:00
|
|
|
val = new KvpValue(g_value_get_int64 (gval));
|
2014-05-07 08:37:14 -05:00
|
|
|
else if (type == G_TYPE_DOUBLE)
|
2015-06-30 14:04:34 -05:00
|
|
|
val = new KvpValue(g_value_get_double (gval));
|
2015-05-07 18:12:54 -05:00
|
|
|
else if (type == G_TYPE_BOOLEAN)
|
2015-06-30 14:04:34 -05:00
|
|
|
{
|
|
|
|
auto bval = g_value_get_boolean(gval);
|
|
|
|
if (bval)
|
|
|
|
val = new KvpValue(g_strdup("true"));
|
|
|
|
}
|
2014-05-07 08:37:14 -05:00
|
|
|
else if (type == GNC_TYPE_NUMERIC)
|
2015-06-30 14:04:34 -05:00
|
|
|
val = new KvpValue(*(gnc_numeric*)g_value_get_boxed (gval));
|
2014-05-07 08:37:14 -05:00
|
|
|
else if (type == G_TYPE_STRING)
|
2015-06-30 14:04:34 -05:00
|
|
|
{
|
|
|
|
auto string = g_value_get_string(gval);
|
|
|
|
if (string != nullptr)
|
|
|
|
val = new KvpValue(g_strdup(string));
|
|
|
|
}
|
2014-05-07 08:37:14 -05:00
|
|
|
else if (type == GNC_TYPE_GUID)
|
2015-06-30 14:04:34 -05:00
|
|
|
{
|
|
|
|
auto boxed = g_value_get_boxed(gval);
|
|
|
|
if (boxed != nullptr)
|
|
|
|
val = new KvpValue(guid_copy(static_cast<GncGUID*>(boxed)));
|
|
|
|
}
|
2014-05-07 08:37:14 -05:00
|
|
|
else if (type == GNC_TYPE_TIMESPEC)
|
2015-06-30 14:04:34 -05:00
|
|
|
val = new KvpValue(*(Timespec*)g_value_get_boxed (gval));
|
2014-05-07 08:37:14 -05:00
|
|
|
else if (type == G_TYPE_DATE)
|
2015-06-30 14:04:34 -05:00
|
|
|
val = new KvpValue(*(GDate*)g_value_get_boxed (gval));
|
2014-05-07 08:37:14 -05:00
|
|
|
else if (type == GNC_TYPE_VALUE_LIST)
|
|
|
|
{
|
2015-05-07 18:12:54 -05:00
|
|
|
GList *gvalue_list = (GList*)g_value_get_boxed (gval);
|
|
|
|
GList *kvp_list = NULL;
|
2015-06-30 14:04:34 -05:00
|
|
|
g_list_foreach (gvalue_list, (GFunc)kvp_value_list_from_gvalue,
|
|
|
|
&kvp_list);
|
2015-05-07 18:12:54 -05:00
|
|
|
kvp_list = g_list_reverse (kvp_list);
|
2015-06-30 14:04:34 -05:00
|
|
|
val = new KvpValue(kvp_list);
|
2015-05-07 18:12:54 -05:00
|
|
|
// g_list_free_full (gvalue_list, (GDestroyNotify)g_value_unset);
|
|
|
|
// gvalue_list = NULL;
|
2014-05-07 08:37:14 -05:00
|
|
|
}
|
|
|
|
else
|
2015-05-07 18:12:54 -05:00
|
|
|
PWARN ("Error! Don't know how to make a KvpValue from a %s",
|
|
|
|
G_VALUE_TYPE_NAME (gval));
|
2014-05-07 08:37:14 -05:00
|
|
|
|
|
|
|
return val;
|
|
|
|
}
|
2015-06-30 14:04:34 -05:00
|
|
|
/* The following are required for using KvpValue GLists as GValues */
|
2014-05-08 20:05:05 -05:00
|
|
|
static void
|
2014-05-07 08:37:14 -05:00
|
|
|
gnc_gvalue_copy (GValue *src, gpointer uData)
|
|
|
|
{
|
2014-05-08 20:05:05 -05:00
|
|
|
GList **new_list = (GList**)uData;
|
2014-05-07 08:37:14 -05:00
|
|
|
GValue *dest = g_value_init (g_slice_new0 (GValue), G_VALUE_TYPE (src));
|
|
|
|
g_value_copy (src, dest);
|
2014-05-08 20:05:05 -05:00
|
|
|
*new_list = g_list_prepend(*new_list, dest);
|
2014-05-07 08:37:14 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gnc_gvalue_free (GValue *val)
|
|
|
|
{
|
|
|
|
if (val == NULL || ! G_IS_VALUE (val)) return;
|
|
|
|
g_value_unset (val);
|
|
|
|
g_slice_free (GValue, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
static GList*
|
|
|
|
gnc_value_list_copy (GList *list)
|
|
|
|
{
|
2014-05-08 20:05:05 -05:00
|
|
|
GList *new_list = NULL;
|
|
|
|
g_list_foreach (list, (GFunc)gnc_gvalue_copy, &new_list);
|
|
|
|
new_list = g_list_reverse (new_list);
|
|
|
|
return new_list;
|
2014-05-07 08:37:14 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gnc_value_list_free (GList *list)
|
|
|
|
{
|
|
|
|
g_list_free_full (list, (GDestroyNotify)gnc_gvalue_free);
|
|
|
|
}
|
|
|
|
|
|
|
|
GType
|
|
|
|
gnc_value_list_get_type (void)
|
|
|
|
{
|
|
|
|
static GType type = 0;
|
|
|
|
if (type == 0)
|
|
|
|
{
|
2015-05-07 18:12:54 -05:00
|
|
|
type = g_boxed_type_register_static ("gnc_value_list",
|
|
|
|
(GBoxedCopyFunc)gnc_value_list_copy,
|
|
|
|
(GBoxedFreeFunc)gnc_value_list_free);
|
2014-05-07 08:37:14 -05:00
|
|
|
}
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
2005-11-07 09:45:58 -06:00
|
|
|
/* ========================== END OF FILE ======================= */
|