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