|
GnuCash 2.4.99
|
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 =============================*/
1.7.4