kvp-util.c

00001 /********************************************************************\
00002  * kvp_util.c -- misc odd-job kvp utils                             *
00003  * Copyright (C) 2001 Linas Vepstas <linas@linas.org>               *
00004  *                                                                  *
00005  * This program is free software; you can redistribute it and/or    *
00006  * modify it under the terms of the GNU General Public License as   *
00007  * published by the Free Software Foundation; either version 2 of   *
00008  * the License, or (at your option) any later version.              *
00009  *                                                                  *
00010  * This program is distributed in the hope that it will be useful,  *
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
00013  * GNU General Public License for more details.                     *
00014  *                                                                  *
00015  * You should have received a copy of the GNU General Public License*
00016  * along with this program; if not, contact:                        *
00017  *                                                                  *
00018  * Free Software Foundation           Voice:  +1-617-542-5942       *
00019  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
00020  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
00021  *                                                                  *
00022 \********************************************************************/
00023 
00024 #include "config.h"
00025 
00026 #include <glib.h>
00027 #include <stdio.h>
00028 
00029 #include "kvp_frame.h"
00030 #include "kvp-util.h"
00031 #include "kvp-util-p.h"
00032 
00033 /* ================================================================ */
00034  
00035 static KvpFrame *
00036 gnc_kvp_array_va (KvpFrame *kvp_root, const char * path, 
00037                   time_t secs, const char * first_name, va_list ap)
00038 {
00039    KvpFrame *cwd;
00040    Timespec ts;
00041    const char *name;
00042 
00043    if (!kvp_root) return NULL;  
00044    if (!first_name) return NULL;
00045    
00046    /* Create subdirectory and put the actual data */
00047    cwd = kvp_frame_new();
00048 
00049    /* Record the time */
00050    ts.tv_sec = secs;
00051    ts.tv_nsec = 0;
00052    kvp_frame_set_timespec (cwd, "date", ts);
00053 
00054    /* Loop over the args */
00055    name = first_name;
00056    while (name)
00057    {
00058       const GUID *guid;
00059       guid = va_arg (ap, const GUID *);
00060 
00061       kvp_frame_set_guid (cwd, name, guid);
00062 
00063       name = va_arg (ap, const char *);
00064    }
00065 
00066    /* Attach cwd into the array */
00067    kvp_frame_add_frame_nc (kvp_root, path, cwd);
00068    return cwd;
00069 }
00070 
00071 /* ================================================================ */
00072 
00073 KvpFrame *
00074 gnc_kvp_bag_add (KvpFrame *pwd, const char * path, 
00075                  time_t secs, const char *first_name, ...)
00076 {
00077    KvpFrame *cwd;
00078    va_list ap;
00079    va_start (ap, first_name);
00080    cwd = gnc_kvp_array_va (pwd, path, secs, first_name, ap);
00081    va_end (ap);
00082    return cwd;
00083 }
00084 
00085 /* ================================================================ */
00086 
00087 #define MATCH_GUID(elt) {                                       \
00088   KvpFrame *fr = kvp_value_get_frame (elt);                     \
00089   if (fr) {                                                     \
00090      GUID *guid = kvp_frame_get_guid (fr, guid_name);           \
00091      if (guid && guid_equal (desired_guid, guid)) return fr;    \
00092   }                                                             \
00093 } 
00094 
00095 KvpFrame *
00096 gnc_kvp_bag_find_by_guid (KvpFrame *root, const char * path,
00097                          const char *guid_name, GUID *desired_guid)
00098 {
00099   KvpValue *arr;
00100   KvpValueType valtype;
00101   GList *node;
00102 
00103   arr = kvp_frame_get_value (root, path);
00104   valtype = kvp_value_get_type (arr);
00105   if (KVP_TYPE_FRAME == valtype)
00106   {
00107     MATCH_GUID (arr);
00108     return NULL;
00109   }
00110 
00111   /* Its gotta be a single isolated frame, or a list of them. */
00112   if (KVP_TYPE_GLIST != valtype) return NULL;
00113 
00114   for (node = kvp_value_get_glist(arr); node; node=node->next)
00115   {
00116     KvpValue *va = node->data;
00117     MATCH_GUID (va);
00118   }
00119   return NULL;
00120 }
00121 
00122 /* ================================================================ */
00123 
00124 void
00125 gnc_kvp_bag_remove_frame (KvpFrame *root, const char *path, KvpFrame *fr)
00126 {
00127   KvpValue *arr;
00128   KvpValueType valtype;
00129   GList *node, *listhead;
00130 
00131   arr = kvp_frame_get_value (root, path);
00132   valtype = kvp_value_get_type (arr);
00133   if (KVP_TYPE_FRAME == valtype)
00134   {
00135     if (fr == kvp_value_get_frame (arr))
00136     {
00137       KvpValue *old_val = kvp_frame_replace_value_nc (root, path, NULL); 
00138       kvp_value_replace_frame_nc (old_val, NULL);
00139       kvp_value_delete (old_val);
00140     }
00141     return;
00142   }
00143 
00144   /* Its gotta be a single isolated frame, or a list of them. */
00145   if (KVP_TYPE_GLIST != valtype) return;
00146 
00147   listhead = kvp_value_get_glist(arr);
00148   for (node = listhead; node; node=node->next)
00149   {
00150     KvpValue *va = node->data;
00151     if (fr == kvp_value_get_frame (va))
00152     {
00153       listhead = g_list_remove_link (listhead, node);
00154       g_list_free_1 (node);
00155       kvp_value_replace_glist_nc (arr, listhead);
00156       kvp_value_replace_frame_nc (va, NULL);
00157       kvp_value_delete (va);
00158       return;
00159     }
00160   }
00161 }
00162 
00163 /* ================================================================ */
00164 
00165 static KvpFrame *
00166 gnc_kvp_bag_get_first (KvpFrame *root, const char * path)
00167 {
00168   KvpValue *arr, *va;
00169   KvpValueType valtype;
00170   GList *node;
00171 
00172   arr = kvp_frame_get_value (root, path);
00173   valtype = kvp_value_get_type (arr);
00174   if (KVP_TYPE_FRAME == valtype)
00175   {
00176     return kvp_value_get_frame(arr);
00177   }
00178 
00179   /* Its gotta be a single isolated frame, or a list of them. */
00180   if (KVP_TYPE_GLIST != valtype) return NULL;
00181 
00182   node = kvp_value_get_glist(arr);
00183   if (NULL == node) return NULL;
00184 
00185   va = node->data;
00186   return kvp_value_get_frame(va);
00187 }
00188 
00189 void
00190 gnc_kvp_bag_merge (KvpFrame *kvp_into, const char *intopath,
00191                    KvpFrame *kvp_from, const char *frompath)
00192 {
00193   KvpFrame *fr;
00194 
00195   fr = gnc_kvp_bag_get_first (kvp_from, frompath);
00196   while (fr) 
00197   {
00198     gnc_kvp_bag_remove_frame (kvp_from, frompath, fr);
00199     kvp_frame_add_frame_nc (kvp_into, intopath, fr);
00200     fr = gnc_kvp_bag_get_first (kvp_from, frompath);
00201   }
00202 }
00203 
00204 /* ================================================================ */
00205 /*
00206  * See header for docs.
00207  */
00208 
00209 static void
00210 kv_pair_helper(gpointer key, gpointer val, gpointer user_data)
00211 {
00212   GSList **result = (GSList **) user_data;
00213   GHashTableKVPair *kvp = g_new(GHashTableKVPair, 1);
00214 
00215   kvp->key = key;
00216   kvp->value = val;
00217   *result = g_slist_prepend(*result, kvp);
00218 }
00219 
00220 GSList *
00221 g_hash_table_key_value_pairs(GHashTable *table)
00222 {
00223   GSList *result_list = NULL;
00224   g_hash_table_foreach(table, kv_pair_helper, &result_list);
00225   return result_list;
00226 }
00227 
00228 void
00229 g_hash_table_kv_pair_free_gfunc(gpointer data, gpointer user_data)
00230 {
00231   GHashTableKVPair *kvp = (GHashTableKVPair *) data;
00232   g_free(kvp);
00233 }
00234 
00235 /*======================== END OF FILE =============================*/

Generated on Fri May 12 17:57:20 2006 for QOF by  doxygen 1.4.4