2005-11-07 09:45:58 -06:00
|
|
|
/********************************************************************
|
|
|
|
* kvp_frame.c -- Implements a key-value frame system *
|
|
|
|
* 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
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C"
|
|
|
|
{
|
|
|
|
#endif
|
|
|
|
|
2005-11-07 09:45:58 -06:00
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <math.h>
|
|
|
|
|
2014-04-25 15:41:11 -05:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-01-08 11:51:29 -06:00
|
|
|
#include "qof.h"
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2012-05-21 12:28:30 -05:00
|
|
|
/* Note that we keep the keys for this hash table in the
|
|
|
|
* qof_string_cache, as it is very likely we will see the
|
2009-09-18 14:40:57 -05:00
|
|
|
* same keys over and over again */
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
struct _KvpFrame
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
GHashTable * hash;
|
2005-11-07 09:45:58 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
typedef struct
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
void *data;
|
|
|
|
int datasize;
|
2005-11-07 09:45:58 -06:00
|
|
|
} KvpValueBinaryData;
|
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
struct _KvpValue
|
|
|
|
{
|
|
|
|
KvpValueType type;
|
|
|
|
union
|
|
|
|
{
|
|
|
|
gint64 int64;
|
|
|
|
double dbl;
|
|
|
|
gnc_numeric numeric;
|
|
|
|
gchar *str;
|
2010-03-27 16:01:21 -05:00
|
|
|
GncGUID *guid;
|
2009-09-18 14:40:57 -05:00
|
|
|
Timespec timespec;
|
|
|
|
KvpValueBinaryData binary;
|
|
|
|
GList *list;
|
|
|
|
KvpFrame *frame;
|
2010-03-17 14:23:20 -05:00
|
|
|
GDate gdate;
|
2009-09-18 14:40:57 -05:00
|
|
|
} value;
|
2005-11-07 09:45:58 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
/* This static indicates the debugging module that this .o belongs to. */
|
|
|
|
static QofLogModule log_module = QOF_MOD_KVP;
|
|
|
|
|
2006-01-08 11:51:29 -06:00
|
|
|
/* *******************************************************************
|
2005-11-07 09:45:58 -06:00
|
|
|
* KvpFrame functions
|
|
|
|
********************************************************************/
|
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
static guint
|
|
|
|
kvp_hash_func(gconstpointer v)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
return g_str_hash(v);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_comp_func(gconstpointer v, gconstpointer v2)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
return g_str_equal(v, v2);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2009-09-18 14:40:57 -05:00
|
|
|
init_frame_body_if_needed(KvpFrame *f)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!f->hash)
|
|
|
|
{
|
|
|
|
f->hash = g_hash_table_new(&kvp_hash_func, &kvp_comp_func);
|
|
|
|
}
|
|
|
|
return(f->hash != NULL);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpFrame *
|
|
|
|
kvp_frame_new(void)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpFrame * retval = g_new0(KvpFrame, 1);
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
/* Save space until the frame is actually used */
|
|
|
|
retval->hash = NULL;
|
|
|
|
return retval;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_delete_worker(gpointer key, gpointer value, gpointer user_data)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2012-05-21 12:28:30 -05:00
|
|
|
qof_string_cache_remove(key);
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_delete((KvpValue *)value);
|
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;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
if (frame->hash)
|
|
|
|
{
|
|
|
|
/* free any allocated resource for frame or its children */
|
|
|
|
g_hash_table_foreach(frame->hash, & kvp_frame_delete_worker,
|
|
|
|
(gpointer)frame);
|
|
|
|
|
|
|
|
/* delete the hash table */
|
|
|
|
g_hash_table_destroy(frame->hash);
|
|
|
|
frame->hash = NULL;
|
|
|
|
}
|
|
|
|
g_free(frame);
|
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
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!frame) return TRUE;
|
|
|
|
if (!frame->hash) return TRUE;
|
|
|
|
return FALSE;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_copy_worker(gpointer key, gpointer value, gpointer user_data)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpFrame * dest = (KvpFrame *)user_data;
|
|
|
|
g_hash_table_insert(dest->hash,
|
2012-05-21 12:28:30 -05:00
|
|
|
qof_string_cache_insert(key),
|
2014-04-25 15:41:11 -05:00
|
|
|
static_cast<void*>(kvp_value_copy(static_cast<KvpValue*>(value))));
|
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
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpFrame * retval = kvp_frame_new();
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!frame) return retval;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
if (frame->hash)
|
|
|
|
{
|
|
|
|
if (!init_frame_body_if_needed(retval)) return(NULL);
|
|
|
|
g_hash_table_foreach(frame->hash,
|
|
|
|
& kvp_frame_copy_worker,
|
|
|
|
(gpointer)retval);
|
|
|
|
}
|
|
|
|
return retval;
|
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 *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_replace_slot_nc (KvpFrame * frame, const char * slot,
|
|
|
|
KvpValue * new_value)
|
|
|
|
{
|
|
|
|
gpointer orig_key;
|
|
|
|
gpointer orig_value = NULL;
|
|
|
|
int key_exists;
|
|
|
|
|
|
|
|
if (!frame || !slot) return NULL;
|
|
|
|
if (!init_frame_body_if_needed(frame)) return NULL; /* Error ... */
|
|
|
|
|
|
|
|
key_exists = g_hash_table_lookup_extended(frame->hash, slot,
|
|
|
|
& orig_key, & orig_value);
|
|
|
|
if (key_exists)
|
|
|
|
{
|
|
|
|
g_hash_table_remove(frame->hash, slot);
|
2012-05-21 12:28:30 -05:00
|
|
|
qof_string_cache_remove(orig_key);
|
2009-09-18 14:40:57 -05:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
orig_value = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (new_value)
|
|
|
|
{
|
|
|
|
g_hash_table_insert(frame->hash,
|
2012-05-21 12:28:30 -05:00
|
|
|
qof_string_cache_insert((gpointer) slot),
|
2009-09-18 14:40:57 -05:00
|
|
|
new_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (KvpValue *) orig_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
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_set_slot_destructively(KvpFrame * frame, const char * slot,
|
|
|
|
KvpValue * new_value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue * old_value;
|
|
|
|
old_value = kvp_frame_replace_slot_nc (frame, slot, new_value);
|
|
|
|
kvp_value_delete (old_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
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
last_key = strrchr (key_path, '/');
|
|
|
|
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;
|
|
|
|
|
|
|
|
last_key = strrchr (key_path, '/');
|
|
|
|
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;
|
|
|
|
KvpValue *oldvalue;
|
|
|
|
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);
|
|
|
|
oldvalue = kvp_frame_get_slot (frame, key);
|
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
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
/* If already a glist here, just append */
|
|
|
|
if (KVP_TYPE_GLIST == oldvalue->type)
|
|
|
|
{
|
|
|
|
GList * vlist = oldvalue->value.list;
|
|
|
|
vlist = g_list_append (vlist, value);
|
|
|
|
oldvalue->value.list = vlist;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
/* If some other value, convert it to a glist */
|
|
|
|
{
|
|
|
|
KvpValue *klist;
|
|
|
|
GList *vlist = NULL;
|
|
|
|
|
|
|
|
vlist = g_list_append (vlist, oldvalue);
|
|
|
|
vlist = g_list_append (vlist, value);
|
|
|
|
klist = kvp_value_new_glist_nc (vlist);
|
|
|
|
|
|
|
|
kvp_frame_replace_slot_nc (frame, key, klist);
|
|
|
|
}
|
|
|
|
LEAVE ("new frame=%s", kvp_frame_to_string(frame));
|
|
|
|
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,
|
|
|
|
const KvpValue * value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue *new_value = NULL;
|
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 (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);
|
|
|
|
kvp_frame_set_slot_destructively(frame, 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;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
g_return_if_fail (slot && *slot != '\0');
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_set_slot_destructively(frame, 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
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue *v;
|
|
|
|
if (!frame) return NULL;
|
|
|
|
if (!frame->hash) return NULL; /* Error ... */
|
2014-04-25 15:41:11 -05:00
|
|
|
v = static_cast<KvpValue*>(g_hash_table_lookup(frame->hash, slot));
|
2009-09-18 14:40:57 -05:00
|
|
|
return v;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ============================================================ */
|
|
|
|
|
|
|
|
void
|
|
|
|
kvp_frame_set_slot_path (KvpFrame *frame,
|
|
|
|
const 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,
|
|
|
|
const 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-04-25 15:41:11 -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 *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_new_gint64(gint64 value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue * retval = g_new0(KvpValue, 1);
|
|
|
|
retval->type = KVP_TYPE_GINT64;
|
|
|
|
retval->value.int64 = value;
|
|
|
|
return retval;
|
|
|
|
}
|
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
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue * retval = g_new0(KvpValue, 1);
|
|
|
|
retval->type = KVP_TYPE_DOUBLE;
|
|
|
|
retval->value.dbl = value;
|
|
|
|
return retval;
|
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
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue * retval = g_new0(KvpValue, 1);
|
|
|
|
retval->type = KVP_TYPE_NUMERIC;
|
|
|
|
retval->value.numeric = value;
|
|
|
|
return retval;
|
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
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue * retval;
|
|
|
|
if (!value) return NULL;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
retval = g_new0(KvpValue, 1);
|
|
|
|
retval->type = KVP_TYPE_STRING;
|
|
|
|
retval->value.str = g_strdup(value);
|
|
|
|
return retval;
|
|
|
|
}
|
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
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue * retval;
|
|
|
|
if (!value) return NULL;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
retval = g_new0(KvpValue, 1);
|
|
|
|
retval->type = KVP_TYPE_GUID;
|
2010-03-27 16:01:21 -05:00
|
|
|
retval->value.guid = g_new0(GncGUID, 1);
|
|
|
|
memcpy(retval->value.guid, value, sizeof(GncGUID));
|
2009-09-18 14:40:57 -05:00
|
|
|
return retval;
|
|
|
|
}
|
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
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue * retval = g_new0(KvpValue, 1);
|
|
|
|
retval->type = KVP_TYPE_TIMESPEC;
|
|
|
|
retval->value.timespec = value;
|
|
|
|
return retval;
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2010-03-17 14:23:20 -05:00
|
|
|
KvpValue *
|
|
|
|
kvp_value_new_gdate(GDate value)
|
|
|
|
{
|
|
|
|
KvpValue * retval = g_new0(KvpValue, 1);
|
|
|
|
retval->type = KVP_TYPE_GDATE;
|
|
|
|
retval->value.gdate = value;
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2005-11-07 09:45:58 -06:00
|
|
|
KvpValue *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_new_binary(const void * value, guint64 datasize)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue * retval;
|
|
|
|
if (!value) return NULL;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
retval = g_new0(KvpValue, 1);
|
|
|
|
retval->type = KVP_TYPE_BINARY;
|
|
|
|
retval->value.binary.data = g_new0(char, datasize);
|
|
|
|
retval->value.binary.datasize = datasize;
|
|
|
|
memcpy(retval->value.binary.data, value, datasize);
|
|
|
|
return retval;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
KvpValue *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_new_binary_nc(void * value, guint64 datasize)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue * retval;
|
|
|
|
if (!value) return NULL;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
retval = g_new0(KvpValue, 1);
|
|
|
|
retval->type = KVP_TYPE_BINARY;
|
|
|
|
retval->value.binary.data = value;
|
|
|
|
retval->value.binary.datasize = datasize;
|
|
|
|
return retval;
|
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
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue * retval;
|
|
|
|
if (!value) return NULL;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
retval = g_new0(KvpValue, 1);
|
|
|
|
retval->type = KVP_TYPE_GLIST;
|
|
|
|
retval->value.list = kvp_glist_copy(value);
|
|
|
|
return retval;
|
|
|
|
}
|
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
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue * retval;
|
|
|
|
if (!value) return NULL;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
retval = g_new0(KvpValue, 1);
|
|
|
|
retval->type = KVP_TYPE_GLIST;
|
|
|
|
retval->value.list = value;
|
|
|
|
return retval;
|
|
|
|
}
|
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
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue * retval;
|
|
|
|
if (!value) return NULL;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
retval = g_new0(KvpValue, 1);
|
|
|
|
retval->type = KVP_TYPE_FRAME;
|
|
|
|
retval->value.frame = kvp_frame_copy(value);
|
|
|
|
return retval;
|
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
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpValue * retval;
|
|
|
|
if (!value) return NULL;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
retval = g_new0(KvpValue, 1);
|
|
|
|
retval->type = KVP_TYPE_FRAME;
|
|
|
|
retval->value.frame = value;
|
|
|
|
return retval;
|
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;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
switch (value->type)
|
|
|
|
{
|
|
|
|
case KVP_TYPE_STRING:
|
|
|
|
g_free(value->value.str);
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_GUID:
|
|
|
|
g_free(value->value.guid);
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_BINARY:
|
|
|
|
g_free(value->value.binary.data);
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_GLIST:
|
|
|
|
kvp_glist_delete(value->value.list);
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_FRAME:
|
|
|
|
kvp_frame_delete(value->value.frame);
|
|
|
|
break;
|
|
|
|
|
2014-04-25 15:41:11 -05:00
|
|
|
default:
|
2009-09-18 14:40:57 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
g_free(value);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
KvpValueType
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_get_type(const KvpValue * value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2014-04-25 15:41:11 -05:00
|
|
|
if (!value) return KVP_TYPE_INVALID;
|
2009-09-18 14:40:57 -05:00
|
|
|
return value->type;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
gint64
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_get_gint64(const KvpValue * value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!value) return 0;
|
|
|
|
if (value->type == KVP_TYPE_GINT64)
|
|
|
|
{
|
|
|
|
return value->value.int64;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
double
|
|
|
|
kvp_value_get_double(const KvpValue * value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!value) return 0.0;
|
|
|
|
if (value->type == KVP_TYPE_DOUBLE)
|
|
|
|
{
|
|
|
|
return value->value.dbl;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0.0;
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
gnc_numeric
|
|
|
|
kvp_value_get_numeric(const KvpValue * value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!value) return gnc_numeric_zero ();
|
|
|
|
if (value->type == KVP_TYPE_NUMERIC)
|
|
|
|
{
|
|
|
|
return value->value.numeric;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return gnc_numeric_zero ();
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_get_string(const KvpValue * value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!value) return NULL;
|
|
|
|
if (value->type == KVP_TYPE_STRING)
|
|
|
|
{
|
|
|
|
return value->value.str;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2010-03-27 16:01:21 -05:00
|
|
|
GncGUID *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_get_guid(const KvpValue * value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!value) return NULL;
|
|
|
|
if (value->type == KVP_TYPE_GUID)
|
|
|
|
{
|
|
|
|
return value->value.guid;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
Timespec
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_get_timespec(const KvpValue * value)
|
|
|
|
{
|
|
|
|
Timespec ts;
|
|
|
|
ts.tv_sec = 0;
|
|
|
|
ts.tv_nsec = 0;
|
|
|
|
if (!value) return ts;
|
|
|
|
if (value->type == KVP_TYPE_TIMESPEC)
|
|
|
|
return value->value.timespec;
|
|
|
|
else
|
|
|
|
return ts;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2010-03-17 14:23:20 -05:00
|
|
|
GDate
|
|
|
|
kvp_value_get_gdate(const KvpValue * value)
|
|
|
|
{
|
|
|
|
GDate date;
|
|
|
|
g_date_clear(&date, 1);
|
|
|
|
if (!value) return date;
|
|
|
|
if (value->type == KVP_TYPE_GDATE)
|
|
|
|
return value->value.gdate;
|
|
|
|
else
|
|
|
|
return date;
|
|
|
|
}
|
|
|
|
|
2005-11-07 09:45:58 -06:00
|
|
|
void *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_get_binary(const KvpValue * value, guint64 * size_return)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!value)
|
|
|
|
{
|
|
|
|
if (size_return)
|
|
|
|
*size_return = 0;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (value->type == KVP_TYPE_BINARY)
|
|
|
|
{
|
|
|
|
if (size_return)
|
|
|
|
*size_return = value->value.binary.datasize;
|
|
|
|
return value->value.binary.data;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (size_return)
|
|
|
|
*size_return = 0;
|
|
|
|
return NULL;
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
GList *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_get_glist(const KvpValue * value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!value) return NULL;
|
|
|
|
if (value->type == KVP_TYPE_GLIST)
|
|
|
|
{
|
|
|
|
return value->value.list;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
KvpFrame *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_get_frame(const KvpValue * value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!value) return NULL;
|
|
|
|
if (value->type == KVP_TYPE_FRAME)
|
|
|
|
{
|
|
|
|
return value->value.frame;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
KvpFrame *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_replace_frame_nc(KvpValue *value, KvpFrame * newframe)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
KvpFrame *oldframe;
|
|
|
|
if (!value) return NULL;
|
|
|
|
if (KVP_TYPE_FRAME != value->type) return NULL;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
oldframe = value->value.frame;
|
|
|
|
value->value.frame = newframe;
|
|
|
|
return oldframe;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
GList *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_replace_glist_nc(KvpValue * value, GList *newlist)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
GList *oldlist;
|
|
|
|
if (!value) return NULL;
|
|
|
|
if (KVP_TYPE_GLIST != value->type) return NULL;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
oldlist = value->value.list;
|
|
|
|
value->value.list = newlist;
|
|
|
|
return oldlist;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* manipulators */
|
|
|
|
|
|
|
|
KvpValue *
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_copy(const KvpValue * value)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (!value) return NULL;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
switch (value->type)
|
|
|
|
{
|
|
|
|
case KVP_TYPE_GINT64:
|
|
|
|
return kvp_value_new_gint64(value->value.int64);
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_DOUBLE:
|
|
|
|
return kvp_value_new_double(value->value.dbl);
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_NUMERIC:
|
|
|
|
return kvp_value_new_gnc_numeric(value->value.numeric);
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_STRING:
|
|
|
|
return kvp_value_new_string(value->value.str);
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_GUID:
|
|
|
|
return kvp_value_new_guid(value->value.guid);
|
|
|
|
break;
|
2010-03-17 14:23:20 -05:00
|
|
|
case KVP_TYPE_GDATE:
|
|
|
|
return kvp_value_new_gdate(value->value.gdate);
|
|
|
|
break;
|
2009-09-18 14:40:57 -05:00
|
|
|
case KVP_TYPE_TIMESPEC:
|
|
|
|
return kvp_value_new_timespec(value->value.timespec);
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_BINARY:
|
|
|
|
return kvp_value_new_binary(value->value.binary.data,
|
|
|
|
value->value.binary.datasize);
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_GLIST:
|
|
|
|
return kvp_value_new_glist(value->value.list);
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_FRAME:
|
|
|
|
return kvp_value_new_frame(value->value.frame);
|
|
|
|
break;
|
2014-04-25 15:41:11 -05:00
|
|
|
default:
|
|
|
|
break;
|
2009-09-18 14:40:57 -05:00
|
|
|
}
|
|
|
|
return NULL;
|
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;
|
|
|
|
if (!proc) return;
|
|
|
|
if (!(f->hash)) return;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
g_hash_table_foreach(f->hash, (GHFunc) proc, data);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2010-02-27 12:40:23 -06:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
# define isnan _isnan
|
|
|
|
#endif
|
2005-11-07 09:45:58 -06:00
|
|
|
gint
|
|
|
|
double_compare(double d1, double d2)
|
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (isnan(d1) && isnan(d2)) return 0;
|
|
|
|
if (d1 < d2) return -1;
|
|
|
|
if (d1 > d2) return 1;
|
|
|
|
return 0;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
gint
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_value_compare(const KvpValue * kva, const KvpValue * kvb)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (kva == kvb) return 0;
|
|
|
|
/* nothing is always less than something */
|
|
|
|
if (!kva && kvb) return -1;
|
|
|
|
if (kva && !kvb) return 1;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
if (kva->type < kvb->type) return -1;
|
|
|
|
if (kva->type > kvb->type) return 1;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
switch (kva->type)
|
|
|
|
{
|
|
|
|
case KVP_TYPE_GINT64:
|
|
|
|
if (kva->value.int64 < kvb->value.int64) return -1;
|
|
|
|
if (kva->value.int64 > kvb->value.int64) return 1;
|
|
|
|
return 0;
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_DOUBLE:
|
|
|
|
return double_compare(kva->value.dbl, kvb->value.dbl);
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_NUMERIC:
|
|
|
|
return gnc_numeric_compare (kva->value.numeric, kvb->value.numeric);
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_STRING:
|
|
|
|
return strcmp(kva->value.str, kvb->value.str);
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_GUID:
|
|
|
|
return guid_compare(kva->value.guid, kvb->value.guid);
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_TIMESPEC:
|
|
|
|
return timespec_cmp(&(kva->value.timespec), &(kvb->value.timespec));
|
|
|
|
break;
|
2010-03-17 14:23:20 -05:00
|
|
|
case KVP_TYPE_GDATE:
|
|
|
|
return g_date_compare(&(kva->value.gdate), &(kvb->value.gdate));
|
|
|
|
break;
|
2009-09-18 14:40:57 -05:00
|
|
|
case KVP_TYPE_BINARY:
|
|
|
|
/* I don't know that this is a good compare. Ab is bigger than Acef.
|
|
|
|
But I'm not sure that actually matters here. */
|
|
|
|
if (kva->value.binary.datasize < kvb->value.binary.datasize) return -1;
|
|
|
|
if (kva->value.binary.datasize > kvb->value.binary.datasize) return 1;
|
|
|
|
return memcmp(kva->value.binary.data,
|
|
|
|
kvb->value.binary.data,
|
|
|
|
kva->value.binary.datasize);
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_GLIST:
|
|
|
|
return kvp_glist_compare(kva->value.list, kvb->value.list);
|
|
|
|
break;
|
|
|
|
case KVP_TYPE_FRAME:
|
|
|
|
return kvp_frame_compare(kva->value.frame, kvb->value.frame);
|
|
|
|
break;
|
2014-04-25 15:41:11 -05:00
|
|
|
default:
|
|
|
|
break;
|
2009-09-18 14:40:57 -05:00
|
|
|
}
|
|
|
|
PERR ("reached unreachable code.");
|
|
|
|
return FALSE;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
gint compare;
|
|
|
|
KvpFrame *other_frame;
|
2005-11-07 09:45:58 -06:00
|
|
|
} kvp_frame_cmp_status;
|
|
|
|
|
|
|
|
static void
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_compare_helper(const char *key, KvpValue * val, gpointer data)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_cmp_status *status = (kvp_frame_cmp_status *) data;
|
|
|
|
if (status->compare == 0)
|
|
|
|
{
|
|
|
|
KvpFrame *other_frame = status->other_frame;
|
|
|
|
KvpValue *other_val = kvp_frame_get_slot(other_frame, key);
|
|
|
|
|
|
|
|
if (other_val)
|
|
|
|
{
|
|
|
|
status->compare = kvp_value_compare(val, other_val);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
status->compare = 1;
|
|
|
|
}
|
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
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_cmp_status status;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
if (fa == fb) return 0;
|
|
|
|
/* nothing is always less than something */
|
|
|
|
if (!fa && fb) return -1;
|
|
|
|
if (fa && !fb) return 1;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
/* nothing is always less than something */
|
|
|
|
if (!fa->hash && fb->hash) return -1;
|
|
|
|
if (fa->hash && !fb->hash) return 1;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
status.compare = 0;
|
|
|
|
status.other_frame = (KvpFrame *) fb;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_for_each_slot((KvpFrame *) fa, kvp_frame_compare_helper, &status);
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
if (status.compare != 0)
|
|
|
|
return status.compare;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
status.other_frame = (KvpFrame *) fa;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
kvp_frame_for_each_slot((KvpFrame *) fb, kvp_frame_compare_helper, &status);
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
return(-status.compare);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
gchar*
|
|
|
|
binary_to_string(const void *data, guint32 size)
|
|
|
|
{
|
|
|
|
GString *output;
|
|
|
|
guint32 i;
|
|
|
|
guchar *data_str = (guchar*)data;
|
2009-09-18 14:40:57 -05:00
|
|
|
|
2005-11-07 09:45:58 -06:00
|
|
|
output = g_string_sized_new(size * sizeof(char));
|
2009-09-18 14:40:57 -05:00
|
|
|
|
|
|
|
for (i = 0; i < size; i++)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
|
|
|
g_string_append_printf(output, "%02x", (unsigned int) (data_str[i]));
|
|
|
|
}
|
|
|
|
|
|
|
|
return output->str;
|
|
|
|
}
|
|
|
|
|
2011-04-04 04:25:10 -05:00
|
|
|
static gchar*
|
2005-11-07 09:45:58 -06:00
|
|
|
kvp_value_glist_to_string(const GList *list)
|
|
|
|
{
|
|
|
|
gchar *tmp1;
|
|
|
|
gchar *tmp2;
|
|
|
|
const GList *cursor;
|
|
|
|
|
|
|
|
tmp1 = g_strdup_printf("[ ");
|
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
for (cursor = list; cursor; cursor = cursor->next)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
|
|
|
gchar *tmp3;
|
|
|
|
|
|
|
|
tmp3 = kvp_value_to_string((KvpValue *)cursor->data);
|
|
|
|
tmp2 = g_strdup_printf("%s %s,", tmp1, tmp3 ? tmp3 : "");
|
|
|
|
g_free(tmp1);
|
|
|
|
g_free(tmp3);
|
|
|
|
tmp1 = tmp2;
|
|
|
|
}
|
|
|
|
|
|
|
|
tmp2 = g_strdup_printf("%s ]", tmp1);
|
|
|
|
g_free(tmp1);
|
2009-09-18 14:40:57 -05:00
|
|
|
|
2005-11-07 09:45:58 -06:00
|
|
|
return tmp2;
|
|
|
|
}
|
|
|
|
|
2011-07-17 16:21:59 -05:00
|
|
|
/* struct for kvp frame static funtion testing*/
|
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 );
|
|
|
|
gchar* ( *p_kvp_value_glist_to_string )( const GList *list );
|
|
|
|
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_kvp_value_glist_to_string = kvp_value_glist_to_string;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ----- */
|
|
|
|
|
2005-11-07 09:45:58 -06:00
|
|
|
gchar*
|
|
|
|
kvp_value_to_string(const KvpValue *val)
|
|
|
|
{
|
|
|
|
gchar *tmp1;
|
|
|
|
gchar *tmp2;
|
|
|
|
const gchar *ctmp;
|
2009-09-18 14:40:57 -05:00
|
|
|
|
2005-11-07 09:45:58 -06:00
|
|
|
g_return_val_if_fail(val, NULL);
|
2009-09-18 14:40:57 -05:00
|
|
|
|
|
|
|
switch (kvp_value_get_type(val))
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
|
|
|
case KVP_TYPE_GINT64:
|
|
|
|
return g_strdup_printf("KVP_VALUE_GINT64(%" G_GINT64_FORMAT ")",
|
|
|
|
kvp_value_get_gint64(val));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KVP_TYPE_DOUBLE:
|
|
|
|
return g_strdup_printf("KVP_VALUE_DOUBLE(%g)",
|
|
|
|
kvp_value_get_double(val));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KVP_TYPE_NUMERIC:
|
|
|
|
tmp1 = gnc_numeric_to_string(kvp_value_get_numeric(val));
|
|
|
|
tmp2 = g_strdup_printf("KVP_VALUE_NUMERIC(%s)", tmp1 ? tmp1 : "");
|
|
|
|
g_free(tmp1);
|
|
|
|
return tmp2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KVP_TYPE_STRING:
|
|
|
|
tmp1 = kvp_value_get_string (val);
|
|
|
|
return g_strdup_printf("KVP_VALUE_STRING(%s)", tmp1 ? tmp1 : "");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KVP_TYPE_GUID:
|
2009-09-18 14:40:57 -05:00
|
|
|
/* THREAD-UNSAFE */
|
2005-11-07 09:45:58 -06:00
|
|
|
ctmp = guid_to_string(kvp_value_get_guid(val));
|
|
|
|
tmp2 = g_strdup_printf("KVP_VALUE_GUID(%s)", ctmp ? ctmp : "");
|
|
|
|
return tmp2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KVP_TYPE_TIMESPEC:
|
|
|
|
tmp1 = g_new0 (char, 40);
|
|
|
|
gnc_timespec_to_iso8601_buff (kvp_value_get_timespec (val), tmp1);
|
|
|
|
tmp2 = g_strdup_printf("KVP_VALUE_TIMESPEC(%s)", tmp1);
|
|
|
|
g_free(tmp1);
|
|
|
|
return tmp2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KVP_TYPE_BINARY:
|
|
|
|
{
|
|
|
|
guint64 len;
|
|
|
|
void *data;
|
|
|
|
data = kvp_value_get_binary(val, &len);
|
|
|
|
tmp1 = binary_to_string(data, len);
|
|
|
|
return g_strdup_printf("KVP_VALUE_BINARY(%s)", tmp1 ? tmp1 : "");
|
|
|
|
}
|
2009-09-18 14:40:57 -05:00
|
|
|
break;
|
|
|
|
|
2005-11-07 09:45:58 -06:00
|
|
|
case KVP_TYPE_GLIST:
|
|
|
|
tmp1 = kvp_value_glist_to_string(kvp_value_get_glist(val));
|
|
|
|
tmp2 = g_strdup_printf("KVP_VALUE_GLIST(%s)", tmp1 ? tmp1 : "");
|
|
|
|
g_free(tmp1);
|
|
|
|
return tmp2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KVP_TYPE_FRAME:
|
|
|
|
tmp1 = kvp_frame_to_string(kvp_value_get_frame(val));
|
|
|
|
tmp2 = g_strdup_printf("KVP_VALUE_FRAME(%s)", tmp1 ? tmp1 : "");
|
|
|
|
g_free(tmp1);
|
|
|
|
return tmp2;
|
|
|
|
break;
|
|
|
|
|
2010-03-17 14:23:20 -05:00
|
|
|
case KVP_TYPE_GDATE:
|
|
|
|
return g_strdup_printf("KVP_VALUE_GDATE(%04d-%02d-%02d)",
|
|
|
|
g_date_get_year(&val->value.gdate),
|
|
|
|
g_date_get_month(&val->value.gdate),
|
|
|
|
g_date_get_day(&val->value.gdate));
|
2014-04-25 15:41:11 -05:00
|
|
|
default:
|
|
|
|
break;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
2010-03-17 14:23:20 -05:00
|
|
|
g_assert(FALSE); /* must not be reached */
|
|
|
|
return g_strdup("");
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
kvp_frame_to_string_helper(gpointer key, gpointer value, gpointer data)
|
|
|
|
{
|
|
|
|
gchar *tmp_val;
|
|
|
|
gchar **str = (gchar**)data;
|
|
|
|
gchar *old_data = *str;
|
|
|
|
|
|
|
|
tmp_val = kvp_value_to_string((KvpValue *)value);
|
|
|
|
|
|
|
|
*str = g_strdup_printf("%s %s => %s,\n",
|
|
|
|
*str ? *str : "",
|
|
|
|
key ? (char *) key : "",
|
|
|
|
tmp_val ? tmp_val : "");
|
|
|
|
|
|
|
|
g_free(old_data);
|
|
|
|
g_free(tmp_val);
|
|
|
|
}
|
|
|
|
|
|
|
|
gchar*
|
|
|
|
kvp_frame_to_string(const KvpFrame *frame)
|
|
|
|
{
|
|
|
|
gchar *tmp1;
|
|
|
|
|
|
|
|
g_return_val_if_fail (frame != NULL, NULL);
|
|
|
|
|
|
|
|
tmp1 = g_strdup_printf("{\n");
|
|
|
|
|
|
|
|
if (frame->hash)
|
2009-09-18 14:40:57 -05:00
|
|
|
g_hash_table_foreach(frame->hash, kvp_frame_to_string_helper, &tmp1);
|
2005-11-07 09:45:58 -06:00
|
|
|
|
|
|
|
{
|
|
|
|
gchar *tmp2;
|
|
|
|
tmp2 = g_strdup_printf("%s}\n", tmp1);
|
|
|
|
g_free(tmp1);
|
|
|
|
tmp1 = tmp2;
|
|
|
|
}
|
|
|
|
|
|
|
|
return tmp1;
|
|
|
|
}
|
|
|
|
|
|
|
|
GHashTable*
|
|
|
|
kvp_frame_get_hash(const KvpFrame *frame)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (frame != NULL, NULL);
|
|
|
|
return frame->hash;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ========================== END OF FILE ======================= */
|