GnuCash 2.4.99
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 GncGUID *guid;
00059         guid = va_arg (ap, const GncGUID *);
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      GncGUID *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, const GncGUID *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 =============================*/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines