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
|
|
|
|
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-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;
|
|
|
|
auto spot = m_valuemap.find(key);
|
2015-06-18 15:55:55 -05:00
|
|
|
KvpValue* ret {nullptr};
|
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)
|
|
|
|
{
|
|
|
|
auto cachedkey = static_cast<const char *>(qof_string_cache_insert(key));
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
auto slot = cur_frame->get_slot(key);
|
|
|
|
if (slot == nullptr || slot->get_type() != KVP_TYPE_FRAME)
|
|
|
|
return nullptr;
|
|
|
|
cur_frame = slot->get<KvpFrame*>();
|
|
|
|
}
|
|
|
|
return cur_frame;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
KvpValue*
|
|
|
|
KvpFrameImpl::set(Path path, KvpValue* value) noexcept
|
|
|
|
{
|
|
|
|
const char* last_key = path.back();
|
|
|
|
path.pop_back();
|
|
|
|
auto cur_frame = walk_path_or_nullptr(this, path);
|
|
|
|
if (cur_frame == nullptr)
|
|
|
|
return nullptr;
|
|
|
|
return cur_frame->set(last_key, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
KvpValue*
|
|
|
|
KvpFrameImpl::set_path(Path path, KvpValue* value) noexcept
|
|
|
|
{
|
|
|
|
auto cur_frame = this;
|
|
|
|
const char* last_key = path.back();
|
|
|
|
path.pop_back();
|
|
|
|
for(auto key:path)
|
|
|
|
{
|
|
|
|
auto slot = cur_frame->get_slot(key);
|
|
|
|
if (slot == nullptr || slot->get_type() != KVP_TYPE_FRAME)
|
|
|
|
{
|
|
|
|
auto new_frame = new KvpFrame;
|
|
|
|
delete cur_frame->set(key, new KvpValue{new_frame});
|
|
|
|
cur_frame = new_frame;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
cur_frame = slot->get<KvpFrame*>();
|
|
|
|
}
|
|
|
|
return cur_frame->set(last_key, value);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
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
|
|
|
|
{
|
|
|
|
const char* last_key = path.back();
|
|
|
|
path.pop_back();
|
|
|
|
auto cur_frame = walk_path_or_nullptr(this, path);
|
|
|
|
if (cur_frame == nullptr)
|
|
|
|
return nullptr;
|
|
|
|
return cur_frame->get_slot(last_key);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This static indicates the debugging module that this .o belongs to. */
|
|
|
|
static QofLogModule log_module = QOF_MOD_KVP;
|
|
|
|
|
|
|
|
KvpFrame *
|
|
|
|
kvp_frame_new(void)
|
|
|
|
{
|
|
|
|
auto ret = new KvpFrameImpl();
|
|
|
|
return static_cast<KvpFrame *>(ret);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_delete(KvpFrame * frame)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!frame) return;
|
2014-10-03 21:05:37 -05:00
|
|
|
auto realframe = static_cast<KvpFrameImpl *>(frame);
|
|
|
|
delete realframe;
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2014-10-03 21:05:37 -05:00
|
|
|
const char **
|
|
|
|
kvp_frame_get_keys(const KvpFrame * frame)
|
|
|
|
{
|
|
|
|
if (!frame) return nullptr;
|
|
|
|
auto realframe = static_cast<KvpFrameImpl const *>(frame);
|
|
|
|
const auto & keys = realframe->get_keys();
|
|
|
|
const char ** ret = g_new(const char *, keys.size() + 1);
|
|
|
|
unsigned int spot {0};
|
|
|
|
std::for_each(keys.begin(), keys.end(),
|
|
|
|
[&ret,&spot](const std::string &a)
|
|
|
|
{
|
|
|
|
ret[spot++] = g_strdup(a.c_str());
|
|
|
|
}
|
|
|
|
);
|
|
|
|
ret[keys.size()] = nullptr;
|
|
|
|
return ret;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_is_empty(const KvpFrame * frame)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2015-06-18 15:55:55 -05:00
|
|
|
return frame->empty();
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpFrame *
|
|
|
|
kvp_frame_copy(const KvpFrame * frame)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-10-03 21:05:37 -05:00
|
|
|
auto ret = new KvpFrameImpl(*static_cast<KvpFrameImpl const *>(frame));
|
|
|
|
return ret;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Replace the old value with the new value. Return the old value.
|
2009-09-18 14:40:57 -05:00
|
|
|
* Passing in a null value into this routine has the effect of
|
2005-11-07 09:45:58 -06:00
|
|
|
* removing the key from the KVP tree.
|
|
|
|
*/
|
2011-04-02 15:17:42 -05:00
|
|
|
static KvpValue *
|
2015-06-18 15:55:55 -05:00
|
|
|
kvp_frame_replace_slot_nc (KvpFrame* frame, const char* slot, KvpValue* value)
|
2009-09-18 14:40:57 -05:00
|
|
|
{
|
2015-06-18 15:55:55 -05:00
|
|
|
if (!frame) return nullptr;
|
|
|
|
return frame->set(slot, value);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Passing in a null value into this routine has the effect
|
|
|
|
* of deleting the old value stored at this slot.
|
|
|
|
*/
|
|
|
|
static inline void
|
2015-06-18 15:55:55 -05:00
|
|
|
kvp_frame_set_slot_destructively(KvpFrame* frame, const char* slot,
|
|
|
|
KvpValue* value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2015-06-18 15:55:55 -05:00
|
|
|
delete frame->set(slot, value);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ============================================================ */
|
|
|
|
/* Get the named frame, or create it if it doesn't exist.
|
|
|
|
* gcc -O3 should inline it. It performs no error checks,
|
|
|
|
* the caller is responsible of passing good keys and frames.
|
|
|
|
*/
|
|
|
|
static inline KvpFrame *
|
|
|
|
get_or_make (KvpFrame *fr, const char * key)
|
|
|
|
{
|
|
|
|
KvpFrame *next_frame;
|
|
|
|
KvpValue *value;
|
|
|
|
|
|
|
|
value = kvp_frame_get_slot (fr, key);
|
2009-09-18 14:40:57 -05:00
|
|
|
if (value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
next_frame = kvp_value_get_frame (value);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
next_frame = kvp_frame_new ();
|
|
|
|
kvp_frame_set_slot_nc (fr, key,
|
|
|
|
kvp_value_new_frame_nc (next_frame));
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
return next_frame;
|
|
|
|
}
|
|
|
|
|
2006-01-08 11:51:29 -06:00
|
|
|
/* Get pointer to last frame in path. If the path doesn't exist,
|
2009-09-18 14:40:57 -05:00
|
|
|
* it is created. The string stored in keypath will be hopelessly
|
2005-11-07 09:45:58 -06:00
|
|
|
* mangled .
|
|
|
|
*/
|
|
|
|
static inline KvpFrame *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_get_frame_slash_trash (KvpFrame *frame, char *key_path)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
char *key, *next;
|
|
|
|
if (!frame || !key_path) return frame;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
key = key_path;
|
|
|
|
key --;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
while (key)
|
|
|
|
{
|
|
|
|
key ++;
|
|
|
|
while ('/' == *key)
|
|
|
|
{
|
|
|
|
key++;
|
|
|
|
}
|
|
|
|
if (0x0 == *key) break; /* trailing slash */
|
|
|
|
next = strchr (key, '/');
|
|
|
|
if (next) *next = 0x0;
|
|
|
|
|
|
|
|
frame = get_or_make (frame, key);
|
|
|
|
if (!frame) break; /* error - should never happen */
|
|
|
|
|
|
|
|
key = next;
|
|
|
|
}
|
|
|
|
return frame;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ============================================================ */
|
|
|
|
/* Get pointer to last frame in path, or NULL if the path doesn't
|
|
|
|
* exist. The string stored in keypath will be hopelessly mangled .
|
|
|
|
*/
|
|
|
|
static inline const KvpFrame *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_get_frame_or_null_slash_trash (const KvpFrame *frame, char *key_path)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue *value;
|
|
|
|
char *key, *next;
|
|
|
|
if (!frame || !key_path) return NULL;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
key = key_path;
|
|
|
|
key --;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
while (key)
|
|
|
|
{
|
|
|
|
key ++;
|
|
|
|
while ('/' == *key)
|
|
|
|
{
|
|
|
|
key++;
|
|
|
|
}
|
|
|
|
if (0x0 == *key) break; /* trailing slash */
|
|
|
|
next = strchr (key, '/');
|
|
|
|
if (next) *next = 0x0;
|
|
|
|
|
|
|
|
value = kvp_frame_get_slot (frame, key);
|
|
|
|
if (!value) return NULL;
|
|
|
|
frame = kvp_value_get_frame (value);
|
|
|
|
if (!frame) return NULL;
|
|
|
|
|
|
|
|
key = next;
|
|
|
|
}
|
|
|
|
return frame;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Return pointer to last frame in path, and also store the
|
2009-09-18 14:40:57 -05:00
|
|
|
* last dangling part of path in 'end_key'. If path doesn't
|
2005-11-07 09:45:58 -06:00
|
|
|
* exist, it is created.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static inline KvpFrame *
|
2006-01-08 11:51:29 -06:00
|
|
|
get_trailer_make (KvpFrame * frame, const char * key_path, char **end_key)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
char *last_key;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!frame || !key_path || (0 == key_path[0])) return NULL;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2014-04-26 13:10:56 -05:00
|
|
|
last_key = strrchr (const_cast<char*>(key_path), '/');
|
2009-09-18 14:40:57 -05:00
|
|
|
if (NULL == last_key)
|
|
|
|
{
|
|
|
|
last_key = (char *) key_path;
|
|
|
|
}
|
|
|
|
else if (last_key == key_path)
|
|
|
|
{
|
|
|
|
last_key ++;
|
|
|
|
}
|
|
|
|
else if (0 == last_key[1])
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char *root, *lkey;
|
|
|
|
root = g_strdup (key_path);
|
|
|
|
lkey = strrchr (root, '/');
|
|
|
|
*lkey = 0;
|
|
|
|
frame = kvp_frame_get_frame_slash_trash (frame, root);
|
|
|
|
g_free(root);
|
|
|
|
|
|
|
|
last_key ++;
|
|
|
|
}
|
|
|
|
|
|
|
|
*end_key = last_key;
|
|
|
|
return frame;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Return pointer to last frame in path, or NULL if the path
|
|
|
|
* doesn't exist. Also store the last dangling part of path
|
|
|
|
* in 'end_key'.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static inline const KvpFrame *
|
2006-01-08 11:51:29 -06:00
|
|
|
get_trailer_or_null (const KvpFrame * frame, const char * key_path, char **end_key)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
char *last_key;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!frame || !key_path || (0 == key_path[0])) return NULL;
|
|
|
|
|
2014-04-26 13:10:56 -05:00
|
|
|
last_key = strrchr (const_cast<char*>(key_path), '/');
|
2009-09-18 14:40:57 -05:00
|
|
|
if (NULL == last_key)
|
|
|
|
{
|
|
|
|
last_key = (char *) key_path;
|
|
|
|
}
|
|
|
|
else if (last_key == key_path)
|
|
|
|
{
|
|
|
|
last_key ++;
|
|
|
|
}
|
|
|
|
else if (0 == last_key[1])
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char *root, *lkey;
|
|
|
|
root = g_strdup (key_path);
|
|
|
|
lkey = strrchr (root, '/');
|
|
|
|
*lkey = 0;
|
|
|
|
frame = kvp_frame_get_frame_or_null_slash_trash (frame, root);
|
|
|
|
g_free(root);
|
|
|
|
|
|
|
|
last_key ++;
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
*end_key = last_key;
|
|
|
|
return frame;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_set_gint64(KvpFrame * frame, const char * path, gint64 ival)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue *value;
|
|
|
|
value = kvp_value_new_gint64 (ival);
|
|
|
|
frame = kvp_frame_set_value_nc (frame, path, value);
|
|
|
|
if (!frame) kvp_value_delete (value);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_set_double(KvpFrame * frame, const char * path, double dval)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue *value;
|
|
|
|
value = kvp_value_new_double (dval);
|
|
|
|
frame = kvp_frame_set_value_nc (frame, path, value);
|
|
|
|
if (!frame) kvp_value_delete (value);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_set_numeric(KvpFrame * frame, const char * path, gnc_numeric nval)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue *value;
|
|
|
|
value = kvp_value_new_gnc_numeric (nval);
|
|
|
|
frame = kvp_frame_set_value_nc (frame, path, value);
|
|
|
|
if (!frame) kvp_value_delete (value);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_set_string(KvpFrame * frame, const char * path, const char* str)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue *value;
|
|
|
|
value = kvp_value_new_string (str);
|
|
|
|
frame = kvp_frame_set_value_nc (frame, path, value);
|
|
|
|
if (!frame) kvp_value_delete (value);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2010-03-27 16:01:21 -05:00
|
|
|
kvp_frame_set_guid(KvpFrame * frame, const char * path, const GncGUID *guid)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue *value;
|
|
|
|
value = kvp_value_new_guid (guid);
|
|
|
|
frame = kvp_frame_set_value_nc (frame, path, value);
|
|
|
|
if (!frame) kvp_value_delete (value);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_set_timespec(KvpFrame * frame, const char * path, Timespec ts)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue *value;
|
|
|
|
value = kvp_value_new_timespec (ts);
|
|
|
|
frame = kvp_frame_set_value_nc (frame, path, value);
|
|
|
|
if (!frame) kvp_value_delete (value);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_set_frame(KvpFrame * frame, const char * path, KvpFrame *fr)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue *value;
|
|
|
|
value = kvp_value_new_frame (fr);
|
|
|
|
frame = kvp_frame_set_value_nc (frame, path, value);
|
|
|
|
if (!frame) kvp_value_delete (value);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_set_frame_nc(KvpFrame * frame, const char * path, KvpFrame *fr)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue *value;
|
|
|
|
value = kvp_value_new_frame_nc (fr);
|
|
|
|
frame = kvp_frame_set_value_nc (frame, path, value);
|
|
|
|
if (!frame) kvp_value_delete (value);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ============================================================ */
|
|
|
|
|
|
|
|
KvpFrame *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_set_value_nc (KvpFrame * frame, const char * key_path,
|
|
|
|
KvpValue * value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
char *last_key;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
frame = get_trailer_make (frame, key_path, &last_key);
|
|
|
|
if (!frame) return NULL;
|
|
|
|
kvp_frame_set_slot_destructively(frame, last_key, value);
|
|
|
|
return frame;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
KvpFrame *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_set_value (KvpFrame * frame, const char * key_path,
|
|
|
|
const KvpValue * value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue *new_value = NULL;
|
|
|
|
char *last_key;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
frame = get_trailer_make (frame, key_path, &last_key);
|
|
|
|
if (!frame) return NULL;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
if (value) new_value = kvp_value_copy(value);
|
|
|
|
kvp_frame_set_slot_destructively(frame, last_key, new_value);
|
|
|
|
return frame;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
KvpValue *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_replace_value_nc (KvpFrame * frame, const char * key_path,
|
|
|
|
KvpValue * new_value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue * old_value;
|
|
|
|
char *last_key;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
last_key = NULL;
|
|
|
|
if (new_value)
|
|
|
|
{
|
|
|
|
frame = get_trailer_make (frame, key_path, &last_key);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
frame = (KvpFrame *) get_trailer_or_null (frame, key_path, &last_key);
|
|
|
|
}
|
|
|
|
if (!frame) return NULL;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
old_value = kvp_frame_replace_slot_nc (frame, last_key, new_value);
|
|
|
|
return old_value;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2011-04-02 15:17:42 -05:00
|
|
|
static KvpFrame *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_add_value_nc(KvpFrame * frame, const char * path, KvpValue *value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
char *key = NULL;
|
2014-09-19 15:35:03 -05:00
|
|
|
KvpValueImpl * oldvalue;
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpFrame* orig_frame = frame;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
frame = (KvpFrame *) get_trailer_or_null (frame, path, &key);
|
2014-09-19 15:35:03 -05:00
|
|
|
oldvalue = static_cast<KvpValueImpl *> (kvp_frame_get_slot (frame, key));
|
|
|
|
auto newvalue = static_cast<KvpValueImpl *> (value);
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
ENTER ("old frame=%s", kvp_frame_to_string(frame));
|
|
|
|
if (oldvalue)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
kvp_frame_replace_slot_nc (frame, key, oldvalue->add (newvalue));
|
|
|
|
LEAVE ("new frame=%s", kvp_frame_to_string (frame));
|
2009-09-18 14:40:57 -05:00
|
|
|
return frame;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
/* Hmm, if we are here, the path doesn't exist. We need to
|
|
|
|
* create the path, add the value to it. */
|
|
|
|
frame = orig_frame;
|
|
|
|
frame = kvp_frame_set_value_nc (frame, path, value);
|
2005-11-07 09:45:58 -06:00
|
|
|
LEAVE ("new frame=%s", kvp_frame_to_string(frame));
|
|
|
|
return frame;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_add_frame_nc(KvpFrame * frame, const char * path, KvpFrame *fr)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue *value;
|
|
|
|
value = kvp_value_new_frame_nc (fr);
|
|
|
|
frame = kvp_frame_add_value_nc (frame, path, value);
|
|
|
|
if (!frame) kvp_value_delete (value);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ============================================================ */
|
|
|
|
|
|
|
|
void
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_set_slot(KvpFrame * frame, const char * slot,
|
2014-09-19 15:35:03 -05:00
|
|
|
KvpValue * value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2015-06-18 15:55:55 -05:00
|
|
|
KvpValue* new_value{nullptr};
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!frame) return;
|
|
|
|
g_return_if_fail (slot && *slot != '\0');
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
if (value) new_value = kvp_value_copy(value);
|
2015-06-18 15:55:55 -05:00
|
|
|
delete frame->set(slot, new_value);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_set_slot_nc(KvpFrame * frame, const char * slot,
|
|
|
|
KvpValue * value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!frame) return;
|
|
|
|
g_return_if_fail (slot && *slot != '\0');
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2015-06-18 15:55:55 -05:00
|
|
|
frame->set(slot, value);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue *
|
|
|
|
kvp_frame_get_slot(const KvpFrame * frame, const char * slot)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2015-06-18 15:55:55 -05:00
|
|
|
if (!frame) return nullptr;
|
|
|
|
return frame->get_slot(slot);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
kvp_frame_set_slot_path (KvpFrame *frame,
|
2014-09-19 15:35:03 -05:00
|
|
|
KvpValue * new_value,
|
2009-09-18 14:40:57 -05:00
|
|
|
const char *first_key, ...)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
va_list ap;
|
|
|
|
const char *key;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!frame) return;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
g_return_if_fail (first_key && *first_key != '\0');
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
va_start (ap, first_key);
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
key = first_key;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
while (TRUE)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue *value;
|
|
|
|
const char *next_key;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
next_key = va_arg (ap, const char *);
|
|
|
|
if (!next_key)
|
|
|
|
{
|
|
|
|
kvp_frame_set_slot (frame, key, new_value);
|
|
|
|
break;
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
g_return_if_fail (*next_key != '\0');
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
value = kvp_frame_get_slot (frame, key);
|
|
|
|
if (!value)
|
|
|
|
{
|
|
|
|
KvpFrame *new_frame = kvp_frame_new ();
|
|
|
|
KvpValue *frame_value = kvp_value_new_frame (new_frame);
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_set_slot_nc (frame, key, frame_value);
|
|
|
|
|
|
|
|
value = kvp_frame_get_slot (frame, key);
|
|
|
|
if (!value) break;
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
frame = kvp_value_get_frame (value);
|
|
|
|
if (!frame) break;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
key = next_key;
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
va_end (ap);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
kvp_frame_set_slot_path_gslist (KvpFrame *frame,
|
2014-09-19 15:35:03 -05:00
|
|
|
KvpValue * new_value,
|
2009-09-18 14:40:57 -05:00
|
|
|
GSList *key_path)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!frame || !key_path) return;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
while (TRUE)
|
|
|
|
{
|
2014-04-25 15:41:11 -05:00
|
|
|
const char *key = static_cast<char*>(key_path->data);
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue *value;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!key)
|
|
|
|
return;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
g_return_if_fail (*key != '\0');
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
key_path = key_path->next;
|
|
|
|
if (!key_path)
|
|
|
|
{
|
|
|
|
kvp_frame_set_slot (frame, key, new_value);
|
|
|
|
return;
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
value = kvp_frame_get_slot (frame, key);
|
|
|
|
if (!value)
|
|
|
|
{
|
|
|
|
KvpFrame *new_frame = kvp_frame_new ();
|
|
|
|
KvpValue *frame_value = kvp_value_new_frame (new_frame);
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_set_slot_nc (frame, key, frame_value);
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
value = kvp_frame_get_slot (frame, key);
|
|
|
|
if (!value)
|
|
|
|
return;
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
frame = kvp_value_get_frame (value);
|
|
|
|
if (!frame)
|
|
|
|
return;
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
gint64
|
|
|
|
kvp_frame_get_gint64(const KvpFrame *frame, const char *path)
|
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
char *key = NULL;
|
|
|
|
frame = get_trailer_or_null (frame, path, &key);
|
|
|
|
return kvp_value_get_gint64(kvp_frame_get_slot (frame, key));
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
2009-09-18 14:40:57 -05:00
|
|
|
double
|
2005-11-07 09:45:58 -06:00
|
|
|
kvp_frame_get_double(const KvpFrame *frame, const char *path)
|
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
char *key = NULL;
|
|
|
|
frame = get_trailer_or_null (frame, path, &key);
|
|
|
|
return kvp_value_get_double(kvp_frame_get_slot (frame, key));
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
gnc_numeric
|
2005-11-07 09:45:58 -06:00
|
|
|
kvp_frame_get_numeric(const KvpFrame *frame, const char *path)
|
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
char *key = NULL;
|
|
|
|
frame = get_trailer_or_null (frame, path, &key);
|
|
|
|
return kvp_value_get_numeric(kvp_frame_get_slot (frame, key));
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
const char *
|
2005-11-07 09:45:58 -06:00
|
|
|
kvp_frame_get_string(const KvpFrame *frame, const char *path)
|
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
char *key = NULL;
|
|
|
|
frame = get_trailer_or_null (frame, path, &key);
|
|
|
|
return kvp_value_get_string(kvp_frame_get_slot (frame, key));
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2010-03-27 16:01:21 -05:00
|
|
|
GncGUID *
|
2005-11-07 09:45:58 -06:00
|
|
|
kvp_frame_get_guid(const KvpFrame *frame, const char *path)
|
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
char *key = NULL;
|
|
|
|
frame = get_trailer_or_null (frame, path, &key);
|
|
|
|
return kvp_value_get_guid(kvp_frame_get_slot (frame, key));
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
Timespec
|
|
|
|
kvp_frame_get_timespec(const KvpFrame *frame, const char *path)
|
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
char *key = NULL;
|
|
|
|
frame = get_trailer_or_null (frame, path, &key);
|
|
|
|
return kvp_value_get_timespec(kvp_frame_get_slot (frame, key));
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
KvpFrame *
|
|
|
|
kvp_frame_get_frame(const KvpFrame *frame, const char *path)
|
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
char *key = NULL;
|
|
|
|
frame = get_trailer_or_null (frame, path, &key);
|
|
|
|
return kvp_value_get_frame(kvp_frame_get_slot (frame, key));
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
KvpValue *
|
|
|
|
kvp_frame_get_value(const KvpFrame *frame, const char *path)
|
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
char *key = NULL;
|
|
|
|
frame = get_trailer_or_null (frame, path, &key);
|
|
|
|
return kvp_frame_get_slot (frame, key);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ============================================================ */
|
|
|
|
|
|
|
|
KvpFrame *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_get_frame_slash (KvpFrame *frame, const char *key_path)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
char *root;
|
|
|
|
if (!frame || !key_path) return frame;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
root = g_strdup (key_path);
|
|
|
|
frame = kvp_frame_get_frame_slash_trash (frame, root);
|
|
|
|
g_free(root);
|
|
|
|
return frame;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ============================================================ */
|
|
|
|
|
|
|
|
KvpValue *
|
|
|
|
kvp_frame_get_slot_path (KvpFrame *frame,
|
2009-09-18 14:40:57 -05:00
|
|
|
const char *first_key, ...)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
va_list ap;
|
|
|
|
KvpValue *value;
|
|
|
|
const char *key;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!frame || !first_key) return NULL;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
va_start (ap, first_key);
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
key = first_key;
|
|
|
|
value = NULL;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
while (TRUE)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
value = kvp_frame_get_slot (frame, key);
|
|
|
|
if (!value) break;
|
|
|
|
|
|
|
|
key = va_arg (ap, const char *);
|
|
|
|
if (!key) break;
|
|
|
|
|
|
|
|
frame = kvp_value_get_frame (value);
|
|
|
|
if (!frame)
|
|
|
|
{
|
|
|
|
value = NULL;
|
|
|
|
break;
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
va_end (ap);
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
return value;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
KvpValue *
|
|
|
|
kvp_frame_get_slot_path_gslist (KvpFrame *frame,
|
2009-09-18 14:40:57 -05:00
|
|
|
const GSList *key_path)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!frame || !key_path) return NULL;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
while (TRUE)
|
|
|
|
{
|
2014-04-25 15:41:11 -05:00
|
|
|
const char *key = static_cast<const char*>(key_path->data);
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue *value;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2012-12-15 04:30:35 -06:00
|
|
|
if (!key) break;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
value = kvp_frame_get_slot (frame, key);
|
2012-12-15 04:30:35 -06:00
|
|
|
if (!value) break;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
key_path = key_path->next;
|
|
|
|
if (!key_path) return value;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
frame = kvp_value_get_frame (value);
|
2012-12-15 04:30:35 -06:00
|
|
|
if (!frame) break;
|
2009-09-18 14:40:57 -05:00
|
|
|
}
|
2012-12-15 04:30:35 -06:00
|
|
|
return NULL;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2006-01-08 11:51:29 -06:00
|
|
|
/* *******************************************************************
|
2005-11-07 09:45:58 -06:00
|
|
|
* kvp glist functions
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
void
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_glist_delete(GList * list)
|
|
|
|
{
|
|
|
|
GList *node;
|
|
|
|
if (!list) return;
|
|
|
|
|
|
|
|
/* Delete the data in the list */
|
|
|
|
for (node = list; node; node = node->next)
|
|
|
|
{
|
2014-04-25 15:41:11 -05:00
|
|
|
KvpValue *val = static_cast<KvpValue*>(node->data);
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_delete(val);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Free the backbone */
|
|
|
|
g_list_free(list);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
GList *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_glist_copy(const GList * list)
|
|
|
|
{
|
|
|
|
GList * retval = NULL;
|
|
|
|
GList * lptr;
|
|
|
|
|
|
|
|
if (!list) return retval;
|
|
|
|
|
|
|
|
/* Duplicate the backbone of the list (this duplicates the POINTERS
|
|
|
|
* to the values; we need to deep-copy the values separately) */
|
|
|
|
retval = g_list_copy((GList *) list);
|
|
|
|
|
|
|
|
/* This step deep-copies the values */
|
|
|
|
for (lptr = retval; lptr; lptr = lptr->next)
|
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
lptr->data = kvp_value_copy(static_cast<KvpValue *>(lptr->data));
|
2009-09-18 14:40:57 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
gint
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_glist_compare(const GList * list1, const GList * list2)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
const GList *lp1;
|
|
|
|
const GList *lp2;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
if (list1 == list2) return 0;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
/* Nothing is always less than something */
|
|
|
|
if (!list1 && list2) return -1;
|
|
|
|
if (list1 && !list2) return 1;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
lp1 = list1;
|
|
|
|
lp2 = list2;
|
|
|
|
while (lp1 && lp2)
|
|
|
|
{
|
|
|
|
KvpValue *v1 = (KvpValue *) lp1->data;
|
|
|
|
KvpValue *v2 = (KvpValue *) lp2->data;
|
|
|
|
gint vcmp = kvp_value_compare(v1, v2);
|
|
|
|
if (vcmp != 0) return vcmp;
|
|
|
|
lp1 = lp1->next;
|
|
|
|
lp2 = lp2->next;
|
|
|
|
}
|
|
|
|
if (!lp1 && lp2) return -1;
|
|
|
|
if (!lp2 && lp1) return 1;
|
|
|
|
return 0;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2006-01-08 11:51:29 -06:00
|
|
|
/* *******************************************************************
|
2005-11-07 09:45:58 -06:00
|
|
|
* KvpValue functions
|
|
|
|
********************************************************************/
|
|
|
|
|
|
|
|
KvpValue *
|
2014-12-11 16:24:48 -06:00
|
|
|
kvp_value_new_gint64(int64_t value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-12-11 16:24:48 -06:00
|
|
|
return new KvpValueImpl{value};
|
2009-09-18 14:40:57 -05:00
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
|
|
|
|
KvpValue *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_new_double(double value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
return new KvpValueImpl{value};
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2015-05-07 18:12:54 -05:00
|
|
|
KvpValue *
|
|
|
|
kvp_value_new_boolean(gboolean value)
|
|
|
|
{
|
|
|
|
if (!value) return {};
|
|
|
|
return new KvpValueImpl{g_strdup("true")};
|
|
|
|
}
|
|
|
|
|
2005-11-07 09:45:58 -06:00
|
|
|
KvpValue *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_new_numeric(gnc_numeric value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
return new KvpValueImpl{value};
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
KvpValue *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_new_string(const char * value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
if (!value) return {};
|
|
|
|
return new KvpValueImpl{g_strdup(value)};
|
2009-09-18 14:40:57 -05:00
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
|
|
|
|
KvpValue *
|
2010-03-27 16:01:21 -05:00
|
|
|
kvp_value_new_guid(const GncGUID * value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
if (!value) return {};
|
|
|
|
return new KvpValueImpl{guid_copy(value)};
|
2009-09-18 14:40:57 -05:00
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
|
|
|
|
KvpValue *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_new_timespec(Timespec value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
return new KvpValueImpl{value};
|
2009-09-18 14:40:57 -05:00
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2010-03-17 14:23:20 -05:00
|
|
|
KvpValue *
|
|
|
|
kvp_value_new_gdate(GDate value)
|
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
return new KvpValueImpl{value};
|
2010-03-17 14:23:20 -05:00
|
|
|
}
|
|
|
|
|
2005-11-07 09:45:58 -06:00
|
|
|
KvpValue *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_new_glist(const GList * value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
if (!value) return {};
|
|
|
|
return new KvpValueImpl{kvp_glist_copy(value)};
|
2009-09-18 14:40:57 -05:00
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
|
|
|
|
KvpValue *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_new_glist_nc(GList * value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
if (!value) return {};
|
|
|
|
return new KvpValueImpl{value};
|
2009-09-18 14:40:57 -05:00
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
|
|
|
|
KvpValue *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_new_frame(const KvpFrame * value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
if (!value) return {};
|
|
|
|
return new KvpValueImpl{kvp_frame_copy(value)};
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
KvpValue *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_new_frame_nc(KvpFrame * value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
if (!value) return {};
|
|
|
|
return new KvpValueImpl{value};
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_delete(KvpValue * value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!value) return;
|
2014-09-19 15:35:03 -05:00
|
|
|
KvpValueImpl * realvalue {static_cast<KvpValueImpl *>(value)};
|
|
|
|
delete realvalue;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
KvpValueType
|
2014-09-19 15:35:03 -05:00
|
|
|
kvp_value_get_type(const KvpValue * oldval)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
if (!oldval) return KVP_TYPE_INVALID;
|
|
|
|
const KvpValueImpl * value {static_cast<const KvpValueImpl *>(oldval)};
|
|
|
|
return value->get_type();
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2014-12-11 16:24:48 -06:00
|
|
|
int64_t
|
2014-09-19 15:35:03 -05:00
|
|
|
kvp_value_get_gint64(const KvpValue * ovalue)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
if (!ovalue) return {};
|
|
|
|
const KvpValueImpl * value {static_cast<const KvpValueImpl *>(ovalue)};
|
|
|
|
return value->get<int64_t>();
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
double
|
2014-09-19 15:35:03 -05:00
|
|
|
kvp_value_get_double(const KvpValue * ovalue)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
if (!ovalue) return {};
|
|
|
|
const KvpValueImpl * value {static_cast<const KvpValueImpl *>(ovalue)};
|
|
|
|
return value->get<double>();
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2015-05-07 18:12:54 -05:00
|
|
|
bool
|
|
|
|
kvp_value_get_boolean (const KvpValue *ovalue)
|
|
|
|
{
|
|
|
|
if (!ovalue) return {};
|
|
|
|
const KvpValueImpl *value {static_cast<const KvpValueImpl*>(ovalue)};
|
|
|
|
const char* str = value->get<char*>();
|
|
|
|
return str && strcmp(str, "true") == 0;
|
|
|
|
}
|
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
gnc_numeric
|
2014-09-19 15:35:03 -05:00
|
|
|
kvp_value_get_numeric(const KvpValue * ovalue)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
//if (!ovalue) return {}; The code depends on no segfault and zero being returned here.
|
|
|
|
if (!ovalue) return gnc_numeric_zero();
|
|
|
|
const KvpValueImpl * value {static_cast<const KvpValueImpl *>(ovalue)};
|
|
|
|
return value->get<gnc_numeric>();
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2015-06-18 15:02:00 -05:00
|
|
|
const char *
|
2014-09-19 15:35:03 -05:00
|
|
|
kvp_value_get_string(const KvpValue * ovalue)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
if (!ovalue) return {};
|
|
|
|
const KvpValueImpl * value {static_cast<const KvpValueImpl *>(ovalue)};
|
2015-06-18 15:02:00 -05:00
|
|
|
return value->get<const char*>();
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2010-03-27 16:01:21 -05:00
|
|
|
GncGUID *
|
2014-09-19 15:35:03 -05:00
|
|
|
kvp_value_get_guid(const KvpValue * ovalue)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
if (!ovalue) return {};
|
|
|
|
const KvpValueImpl * value {static_cast<const KvpValueImpl *>(ovalue)};
|
|
|
|
return value->get<GncGUID*>();
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
Timespec
|
2014-09-19 15:35:03 -05:00
|
|
|
kvp_value_get_timespec(const KvpValue * ovalue)
|
|
|
|
{
|
|
|
|
if (!ovalue) return {};
|
|
|
|
const KvpValueImpl * value {static_cast<const KvpValueImpl *>(ovalue)};
|
|
|
|
return value->get<Timespec>();
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2010-03-17 14:23:20 -05:00
|
|
|
GDate
|
2014-09-19 15:35:03 -05:00
|
|
|
kvp_value_get_gdate(const KvpValue * ovalue)
|
2010-03-17 14:23:20 -05:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
if (!ovalue) return {};
|
|
|
|
const KvpValueImpl * value {static_cast<const KvpValueImpl *>(ovalue)};
|
|
|
|
return value->get<GDate>();
|
2010-03-17 14:23:20 -05:00
|
|
|
}
|
|
|
|
|
2005-11-07 09:45:58 -06:00
|
|
|
GList *
|
2014-09-19 15:35:03 -05:00
|
|
|
kvp_value_get_glist(const KvpValue * ovalue)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
if (!ovalue) return {};
|
|
|
|
const KvpValueImpl * value {static_cast<const KvpValueImpl *>(ovalue)};
|
|
|
|
return value->get<GList*>();
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
KvpFrame *
|
2014-09-19 15:35:03 -05:00
|
|
|
kvp_value_get_frame(const KvpValue * ovalue)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
if (!ovalue) return {};
|
|
|
|
const KvpValueImpl * value {static_cast<const KvpValueImpl *>(ovalue)};
|
|
|
|
return value->get<KvpFrame*>();
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
KvpFrame *
|
2014-09-19 15:35:03 -05:00
|
|
|
kvp_value_replace_frame_nc(KvpValue * ovalue, KvpFrame * newframe)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
if (!ovalue) return {};
|
|
|
|
KvpValueImpl * value {static_cast<KvpValueImpl *>(ovalue)};
|
|
|
|
return value->replace_frame_nc (newframe);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
GList *
|
2014-09-19 15:35:03 -05:00
|
|
|
kvp_value_replace_glist_nc(KvpValue * ovalue, GList *newlist)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
if (!ovalue) return {};
|
|
|
|
KvpValueImpl * value {static_cast<KvpValueImpl *>(ovalue)};
|
|
|
|
return value->replace_glist_nc (newlist);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
KvpValue *
|
2014-09-19 15:35:03 -05:00
|
|
|
kvp_value_copy(const KvpValue * ovalue)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
if (!ovalue) return {};
|
|
|
|
auto value = static_cast<const KvpValueImpl *>(ovalue);
|
|
|
|
KvpValueImpl * ret = new KvpValueImpl(*value);
|
|
|
|
return static_cast<KvpValue *>(ret);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
kvp_frame_for_each_slot(KvpFrame *f,
|
|
|
|
void (*proc)(const char *key,
|
|
|
|
KvpValue *value,
|
|
|
|
gpointer data),
|
|
|
|
gpointer data)
|
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!f) return;
|
2014-10-03 21:05:37 -05:00
|
|
|
auto realframe = static_cast<KvpFrameImpl *>(f);
|
|
|
|
realframe->for_each_slot(proc, data);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2014-09-19 15:35:03 -05:00
|
|
|
int
|
|
|
|
kvp_value_compare(const KvpValue * okva, const KvpValue * okvb)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
auto kva = static_cast<const KvpValueImpl *>(okva);
|
|
|
|
auto kvb = static_cast<const KvpValueImpl *>(okvb);
|
|
|
|
return compare(kva, kvb);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
gint
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_compare(const KvpFrame *fa, const KvpFrame *fb)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-10-03 21:05:37 -05:00
|
|
|
auto realone = static_cast<const KvpFrameImpl *>(fa);
|
|
|
|
auto realtwo = static_cast<const KvpFrameImpl *>(fb);
|
|
|
|
return compare(realone, realtwo);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2014-09-19 15:35:03 -05:00
|
|
|
char *
|
|
|
|
kvp_value_to_string(const KvpValue * val)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-09-19 15:35:03 -05:00
|
|
|
if (!val) return g_strdup("");
|
|
|
|
auto realval = static_cast<const KvpValueImpl *>(val);
|
|
|
|
return realval->to_string();
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2014-04-25 15:41:11 -05:00
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C"
|
|
|
|
{
|
|
|
|
#endif
|
|
|
|
|
2011-07-17 16:21:59 -05:00
|
|
|
void init_static_test_pointers( void );
|
|
|
|
|
2014-04-25 15:41:11 -05:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-07-17 16:21:59 -05:00
|
|
|
KvpFrame* ( *p_get_trailer_make )( KvpFrame *frame, const char *key_path, char **end_key );
|
|
|
|
KvpFrame* ( *p_get_or_make )( KvpFrame *fr, const char * key );
|
|
|
|
const KvpFrame* ( *p_kvp_frame_get_frame_or_null_slash_trash )( const KvpFrame *frame, char *key_path );
|
|
|
|
const KvpFrame* ( *p_get_trailer_or_null )( const KvpFrame * frame, const char * key_path, char **end_key );
|
|
|
|
|
|
|
|
void
|
|
|
|
init_static_test_pointers( void )
|
|
|
|
{
|
|
|
|
p_get_trailer_make = get_trailer_make;
|
|
|
|
p_get_or_make = get_or_make;
|
|
|
|
p_kvp_frame_get_frame_or_null_slash_trash = kvp_frame_get_frame_or_null_slash_trash;
|
|
|
|
p_get_trailer_or_null = get_trailer_or_null;
|
|
|
|
}
|
|
|
|
|
2014-10-03 21:05:37 -05:00
|
|
|
char*
|
2005-11-07 09:45:58 -06:00
|
|
|
kvp_frame_to_string(const KvpFrame *frame)
|
|
|
|
{
|
2014-10-03 21:05:37 -05:00
|
|
|
auto realframe = static_cast<KvpFrameImpl const *>(frame);
|
|
|
|
/*We'll use g_strdup
|
|
|
|
because it will be freed using g_free.*/
|
|
|
|
return g_strdup(realframe->to_string().c_str());
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2014-05-07 08:37:14 -05:00
|
|
|
static KvpValue *kvp_value_from_gvalue (const GValue*);
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
2014-09-19 15:35:03 -05:00
|
|
|
switch (kvp_value_get_type(kval))
|
2014-05-07 08:37:14 -05:00
|
|
|
{
|
2015-05-07 18:12:54 -05:00
|
|
|
case KVP_TYPE_GINT64:
|
|
|
|
g_value_init (val, G_TYPE_INT64);
|
|
|
|
g_value_set_int64 (val, kvp_value_get_gint64 (kval));
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_DOUBLE:
|
|
|
|
g_value_init (val, G_TYPE_DOUBLE);
|
|
|
|
g_value_set_double (val, kvp_value_get_double (kval));
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_BOOLEAN:
|
|
|
|
g_value_init (val, G_TYPE_BOOLEAN);
|
|
|
|
g_value_set_boolean (val, kvp_value_get_boolean (kval));
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_NUMERIC:
|
|
|
|
g_value_init (val, GNC_TYPE_NUMERIC);
|
|
|
|
num = kvp_value_get_numeric (kval);
|
|
|
|
g_value_set_boxed (val, &num);
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_STRING:
|
|
|
|
g_value_init (val, G_TYPE_STRING);
|
|
|
|
g_value_set_string (val, kvp_value_get_string (kval));
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_GUID:
|
|
|
|
g_value_init (val, GNC_TYPE_GUID);
|
|
|
|
g_value_set_boxed (val, kvp_value_get_guid (kval));
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_TIMESPEC:
|
|
|
|
g_value_init (val, GNC_TYPE_TIMESPEC);
|
|
|
|
tm = kvp_value_get_timespec (kval);
|
|
|
|
g_value_set_boxed (val, &tm);
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_GDATE:
|
|
|
|
g_value_init (val, G_TYPE_DATE);
|
|
|
|
gdate = kvp_value_get_gdate (kval);
|
|
|
|
g_value_set_boxed (val, &gdate);
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_GLIST:
|
|
|
|
{
|
|
|
|
GList *gvalue_list = NULL;
|
|
|
|
GList *kvp_list = kvp_value_get_glist (kval);
|
|
|
|
g_list_foreach (kvp_list, (GFunc)gvalue_list_from_kvp_value, &gvalue_list);
|
|
|
|
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-05-07 18:12:54 -05:00
|
|
|
case KVP_TYPE_FRAME:
|
|
|
|
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-05-07 18:12:54 -05:00
|
|
|
val = kvp_value_new_gint64 (g_value_get_int64 (gval));
|
2014-05-07 08:37:14 -05:00
|
|
|
else if (type == G_TYPE_DOUBLE)
|
2015-05-07 18:12:54 -05:00
|
|
|
val = kvp_value_new_double (g_value_get_double (gval));
|
|
|
|
else if (type == G_TYPE_BOOLEAN)
|
|
|
|
val = kvp_value_new_boolean (g_value_get_boolean (gval));
|
2014-05-07 08:37:14 -05:00
|
|
|
else if (type == GNC_TYPE_NUMERIC)
|
2015-05-07 18:12:54 -05:00
|
|
|
val = kvp_value_new_numeric (*(gnc_numeric*)g_value_get_boxed (gval));
|
2014-05-07 08:37:14 -05:00
|
|
|
else if (type == G_TYPE_STRING)
|
2015-05-07 18:12:54 -05:00
|
|
|
val = kvp_value_new_string (g_value_get_string (gval));
|
2014-05-07 08:37:14 -05:00
|
|
|
else if (type == GNC_TYPE_GUID)
|
2015-05-07 18:12:54 -05:00
|
|
|
val = kvp_value_new_guid ((GncGUID*)g_value_get_boxed (gval));
|
2014-05-07 08:37:14 -05:00
|
|
|
else if (type == GNC_TYPE_TIMESPEC)
|
2015-05-07 18:12:54 -05:00
|
|
|
val = kvp_value_new_timespec (*(Timespec*)g_value_get_boxed (gval));
|
2014-05-07 08:37:14 -05:00
|
|
|
else if (type == G_TYPE_DATE)
|
2015-05-07 18:12:54 -05:00
|
|
|
val = kvp_value_new_gdate (*(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;
|
|
|
|
g_list_foreach (gvalue_list, (GFunc)kvp_value_list_from_gvalue, &kvp_list);
|
|
|
|
kvp_list = g_list_reverse (kvp_list);
|
|
|
|
val = kvp_value_new_glist_nc (kvp_list);
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
GValue*
|
|
|
|
kvp_frame_get_gvalue (KvpFrame *frame, const gchar *key)
|
|
|
|
{
|
|
|
|
KvpValue *kval = kvp_frame_get_value (frame, key);
|
|
|
|
GValue *value = gvalue_from_kvp_value (kval);
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
kvp_frame_set_gvalue (KvpFrame *frame, const gchar *key, const GValue *value)
|
|
|
|
{
|
2015-05-07 18:12:54 -05:00
|
|
|
kvp_frame_set_value_nc (frame, key, kvp_value_from_gvalue (value));
|
2014-05-07 08:37:14 -05:00
|
|
|
}
|
|
|
|
|
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 ======================= */
|