mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
private data structure. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@16039 57a11ea4-9604-0410-9ed3-97b8803252fd
236 lines
6.6 KiB
C
236 lines
6.6 KiB
C
/********************************************************************\
|
|
* kvp_util.c -- misc odd-job kvp utils *
|
|
* Copyright (C) 2001 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 *
|
|
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
|
|
* Boston, MA 02110-1301, USA gnu@gnu.org *
|
|
* *
|
|
\********************************************************************/
|
|
|
|
#include "config.h"
|
|
|
|
#include <glib.h>
|
|
#include <stdio.h>
|
|
|
|
#include "kvp_frame.h"
|
|
#include "kvp-util.h"
|
|
#include "kvp-util-p.h"
|
|
|
|
/* ================================================================ */
|
|
|
|
static KvpFrame *
|
|
gnc_kvp_array_va (KvpFrame *kvp_root, const char * path,
|
|
time_t secs, const char * first_name, va_list ap)
|
|
{
|
|
KvpFrame *cwd;
|
|
Timespec ts;
|
|
const char *name;
|
|
|
|
if (!kvp_root) return NULL;
|
|
if (!first_name) return NULL;
|
|
|
|
/* Create subdirectory and put the actual data */
|
|
cwd = kvp_frame_new();
|
|
|
|
/* Record the time */
|
|
ts.tv_sec = secs;
|
|
ts.tv_nsec = 0;
|
|
kvp_frame_set_timespec (cwd, "date", ts);
|
|
|
|
/* Loop over the args */
|
|
name = first_name;
|
|
while (name)
|
|
{
|
|
const GUID *guid;
|
|
guid = va_arg (ap, const GUID *);
|
|
|
|
kvp_frame_set_guid (cwd, name, guid);
|
|
|
|
name = va_arg (ap, const char *);
|
|
}
|
|
|
|
/* Attach cwd into the array */
|
|
kvp_frame_add_frame_nc (kvp_root, path, cwd);
|
|
return cwd;
|
|
}
|
|
|
|
/* ================================================================ */
|
|
|
|
KvpFrame *
|
|
gnc_kvp_bag_add (KvpFrame *pwd, const char * path,
|
|
time_t secs, const char *first_name, ...)
|
|
{
|
|
KvpFrame *cwd;
|
|
va_list ap;
|
|
va_start (ap, first_name);
|
|
cwd = gnc_kvp_array_va (pwd, path, secs, first_name, ap);
|
|
va_end (ap);
|
|
return cwd;
|
|
}
|
|
|
|
/* ================================================================ */
|
|
|
|
#define MATCH_GUID(elt) { \
|
|
KvpFrame *fr = kvp_value_get_frame (elt); \
|
|
if (fr) { \
|
|
GUID *guid = kvp_frame_get_guid (fr, guid_name); \
|
|
if (guid && guid_equal (desired_guid, guid)) return fr; \
|
|
} \
|
|
}
|
|
|
|
KvpFrame *
|
|
gnc_kvp_bag_find_by_guid (KvpFrame *root, const char * path,
|
|
const char *guid_name, const GUID *desired_guid)
|
|
{
|
|
KvpValue *arr;
|
|
KvpValueType valtype;
|
|
GList *node;
|
|
|
|
arr = kvp_frame_get_value (root, path);
|
|
valtype = kvp_value_get_type (arr);
|
|
if (KVP_TYPE_FRAME == valtype)
|
|
{
|
|
MATCH_GUID (arr);
|
|
return NULL;
|
|
}
|
|
|
|
/* Its gotta be a single isolated frame, or a list of them. */
|
|
if (KVP_TYPE_GLIST != valtype) return NULL;
|
|
|
|
for (node = kvp_value_get_glist(arr); node; node=node->next)
|
|
{
|
|
KvpValue *va = node->data;
|
|
MATCH_GUID (va);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/* ================================================================ */
|
|
|
|
void
|
|
gnc_kvp_bag_remove_frame (KvpFrame *root, const char *path, KvpFrame *fr)
|
|
{
|
|
KvpValue *arr;
|
|
KvpValueType valtype;
|
|
GList *node, *listhead;
|
|
|
|
arr = kvp_frame_get_value (root, path);
|
|
valtype = kvp_value_get_type (arr);
|
|
if (KVP_TYPE_FRAME == valtype)
|
|
{
|
|
if (fr == kvp_value_get_frame (arr))
|
|
{
|
|
KvpValue *old_val = kvp_frame_replace_value_nc (root, path, NULL);
|
|
kvp_value_replace_frame_nc (old_val, NULL);
|
|
kvp_value_delete (old_val);
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* Its gotta be a single isolated frame, or a list of them. */
|
|
if (KVP_TYPE_GLIST != valtype) return;
|
|
|
|
listhead = kvp_value_get_glist(arr);
|
|
for (node = listhead; node; node=node->next)
|
|
{
|
|
KvpValue *va = node->data;
|
|
if (fr == kvp_value_get_frame (va))
|
|
{
|
|
listhead = g_list_remove_link (listhead, node);
|
|
g_list_free_1 (node);
|
|
kvp_value_replace_glist_nc (arr, listhead);
|
|
kvp_value_replace_frame_nc (va, NULL);
|
|
kvp_value_delete (va);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ================================================================ */
|
|
|
|
static KvpFrame *
|
|
gnc_kvp_bag_get_first (KvpFrame *root, const char * path)
|
|
{
|
|
KvpValue *arr, *va;
|
|
KvpValueType valtype;
|
|
GList *node;
|
|
|
|
arr = kvp_frame_get_value (root, path);
|
|
valtype = kvp_value_get_type (arr);
|
|
if (KVP_TYPE_FRAME == valtype)
|
|
{
|
|
return kvp_value_get_frame(arr);
|
|
}
|
|
|
|
/* Its gotta be a single isolated frame, or a list of them. */
|
|
if (KVP_TYPE_GLIST != valtype) return NULL;
|
|
|
|
node = kvp_value_get_glist(arr);
|
|
if (NULL == node) return NULL;
|
|
|
|
va = node->data;
|
|
return kvp_value_get_frame(va);
|
|
}
|
|
|
|
void
|
|
gnc_kvp_bag_merge (KvpFrame *kvp_into, const char *intopath,
|
|
KvpFrame *kvp_from, const char *frompath)
|
|
{
|
|
KvpFrame *fr;
|
|
|
|
fr = gnc_kvp_bag_get_first (kvp_from, frompath);
|
|
while (fr)
|
|
{
|
|
gnc_kvp_bag_remove_frame (kvp_from, frompath, fr);
|
|
kvp_frame_add_frame_nc (kvp_into, intopath, fr);
|
|
fr = gnc_kvp_bag_get_first (kvp_from, frompath);
|
|
}
|
|
}
|
|
|
|
/* ================================================================ */
|
|
/*
|
|
* See header for docs.
|
|
*/
|
|
|
|
static void
|
|
kv_pair_helper(gpointer key, gpointer val, gpointer user_data)
|
|
{
|
|
GSList **result = (GSList **) user_data;
|
|
GHashTableKVPair *kvp = g_new(GHashTableKVPair, 1);
|
|
|
|
kvp->key = key;
|
|
kvp->value = val;
|
|
*result = g_slist_prepend(*result, kvp);
|
|
}
|
|
|
|
GSList *
|
|
g_hash_table_key_value_pairs(GHashTable *table)
|
|
{
|
|
GSList *result_list = NULL;
|
|
g_hash_table_foreach(table, kv_pair_helper, &result_list);
|
|
return result_list;
|
|
}
|
|
|
|
void
|
|
g_hash_table_kv_pair_free_gfunc(gpointer data, gpointer user_data)
|
|
{
|
|
GHashTableKVPair *kvp = (GHashTableKVPair *) data;
|
|
g_free(kvp);
|
|
}
|
|
|
|
/*======================== END OF FILE =============================*/
|