1 /* Fo
2  * fo-hashtable.c: HashTable hashtable
3  *
4  * Copyright (C) 2001 Sun Microsystems
5  * Copyright (C) 2007-2010 Menteith Consulting Ltd
6  *
7  * See COPYING for the status of this software.
8  */
9 
10 #include <math.h>
11 #include "fo-utils.h"
12 #include "fo-hash-table.h"
13 
14 struct _FoHashTable
15 {
16   FoObject parent_instance;
17 
18   GHashTable *hash_table;
19 };
20 
21 struct _FoHashTableClass
22 {
23   FoObjectClass parent_class;
24 };
25 
26 static void     _init           (FoHashTable      *hash_table);
27 static void     _class_init     (FoHashTableClass *klass);
28 static void     _finalize       (GObject          *object);
29 
30 static guint    _hash_func      (gconstpointer     key);
31 static gboolean _key_equal_func (gconstpointer     a,
32 				 gconstpointer     b);
33 static void     _destroy_func   (gpointer          data);
34 
35 static gpointer parent_class;
36 
37 /**
38  * fo_hash_table_get_type:
39  *
40  * Register the #FoHashTable object type.
41  *
42  * Return value: #GType value of the #FoHashTable object type.
43  **/
44 GType
fo_hash_table_get_type(void)45 fo_hash_table_get_type (void)
46 {
47   static GType object_type = 0;
48 
49   if (!object_type)
50     {
51       static const GTypeInfo object_info =
52 	{
53 	  sizeof (FoHashTableClass),
54 	  (GBaseInitFunc) NULL,
55 	  (GBaseFinalizeFunc) NULL,
56 	  (GClassInitFunc) _class_init,
57 	  NULL,           /* class_finalize */
58 	  NULL,           /* class_data */
59 	  sizeof (FoHashTable),
60 	  0,              /* n_preallocs */
61 	  (GInstanceInitFunc) _init,
62 	  NULL		/* value_table */
63 	};
64 
65       object_type = g_type_register_static (FO_TYPE_OBJECT,
66                                             "FoHashTable",
67                                             &object_info,
68 					    0);
69     }
70 
71   return object_type;
72 }
73 
74 /**
75  * _init:
76  * @hash_table: #FoHash_Table object to initialise
77  *
78  * Implements #GInstanceInitFunc for #FoHashTable
79  **/
80 static void
_init(FoHashTable * hash_table)81 _init (FoHashTable *hash_table)
82 {
83   hash_table->hash_table = g_hash_table_new_full(_hash_func,
84 						 _key_equal_func,
85 						 _destroy_func,
86 						 _destroy_func);
87 }
88 
89 /**
90  * _class_init:
91  * @klass: #FoHashTableClass object to initialise.
92  *
93  * Implements #GClassInitFunc for #FoHashTableClass.
94  **/
95 static void
_class_init(FoHashTableClass * klass)96 _class_init (FoHashTableClass *klass)
97 {
98   GObjectClass *object_class = G_OBJECT_CLASS (klass);
99 
100   parent_class = g_type_class_peek_parent (klass);
101 
102   object_class->finalize = _finalize;
103 }
104 
105 /**
106  * _finalize:
107  * @object: #FoHashTable object to finalize.
108  *
109  * Implements #GObjectFinalizeFunc for #FoHashTable.
110  **/
111 static void
_finalize(GObject * object)112 _finalize (GObject *object)
113 {
114   FoHashTable *fo_hash_table;
115 
116   fo_hash_table = FO_HASH_TABLE (object);
117 
118   g_hash_table_destroy (fo_hash_table->hash_table);
119 
120   G_OBJECT_CLASS (parent_class)->finalize (object);
121 }
122 
123 /**
124  * fo_hash_table_new:
125  *
126  * Creates a new #FoHashTable initialized to default value.
127  *
128  * Return value: the new #FoHashTable
129  **/
130 FoHashTable *
fo_hash_table_new(void)131 fo_hash_table_new (void)
132 {
133   return FO_HASH_TABLE (g_object_new (fo_hash_table_get_type (),
134 				      NULL));
135 }
136 
137 /**
138  * _destroy_func:
139  * @data: Data to be destroyed.
140  *
141  * #GDestroyNotify function called when a key or value is removed from
142  * a #FoHashTable.
143  **/
144 static void
_destroy_func(gpointer data)145 _destroy_func (gpointer data)
146 {
147   if ((data != NULL) &&
148       FO_IS_OBJECT (data))
149     {
150       g_object_unref (data);
151     }
152 }
153 
154 /**
155  * _hash_func:
156  * @key: Key to hash.
157  *
158  * Creates the hash code for @key using the 'hash' function for the
159  * #FoObject class type of @key.
160  *
161  * Return value: Hash code for @key.
162  **/
163 static guint
_hash_func(gconstpointer key)164 _hash_func (gconstpointer key)
165 {
166   guint result = 0;
167 
168   if ((key != NULL) &&
169       (FO_IS_OBJECT (key)))
170     {
171       result = FO_OBJECT_GET_CLASS (key)->hash_func (key);
172     }
173 
174   return result;
175 }
176 
177 /**
178  * _key_equal_func:
179  * @a: First key to compare.
180  * @b: Second key to compare.
181  *
182  * Compares @a and @b using the 'equal' function of the #FoObject
183  * class type of @a.
184  *
185  * Return value: %TRUE if @a and @b are equal.
186  **/
187 static gboolean
_key_equal_func(gconstpointer a,gconstpointer b)188 _key_equal_func (gconstpointer a,
189 		 gconstpointer b)
190 {
191   return FO_OBJECT_GET_CLASS (a)->equal_func (a, b);
192 }
193 
194 /**
195  * fo_hash_table_insert:
196  * @fo_hash_table: #FoHashTable in which to insert.
197  * @key:           Key at which to insert.
198  * @value:         Value to insert.
199  * @error:         #GError with information about error that occurred.
200  *
201  * Inserts @value as the value corresponding to @key in
202  * @fo_hash_table.
203  **/
204 void
fo_hash_table_insert(FoHashTable * fo_hash_table,FoObject * key,FoObject * value,GError ** error G_GNUC_UNUSED)205 fo_hash_table_insert (FoHashTable *fo_hash_table,
206 		      FoObject    *key,
207 		      FoObject    *value,
208 		      GError     **error G_GNUC_UNUSED)
209 {
210   g_return_if_fail (fo_hash_table != NULL);
211   g_return_if_fail (FO_IS_HASH_TABLE (fo_hash_table));
212   g_return_if_fail (key != NULL);
213   g_return_if_fail (FO_IS_OBJECT (value));
214 
215   g_hash_table_insert (fo_hash_table->hash_table,
216 		       g_object_ref (key),
217 		       g_object_ref (value));
218 }
219 
220 /**
221  * fo_hash_table_replace:
222  * @fo_hash_table: #FoHashTable in which to replace.
223  * @key:           Key of key-value pair to replace.
224  * @value:         New value.
225  * @error:         #GError with information about error that occurred.
226  *
227  * Replaces the key-value pair in @fo_hash_table that has a key
228  * matching @key.
229  **/
230 void
fo_hash_table_replace(FoHashTable * fo_hash_table,FoObject * key,FoObject * value,GError ** error G_GNUC_UNUSED)231 fo_hash_table_replace (FoHashTable *fo_hash_table,
232 		       FoObject    *key,
233 		       FoObject    *value,
234 		       GError     **error G_GNUC_UNUSED)
235 {
236   g_return_if_fail (fo_hash_table != NULL);
237   g_return_if_fail (FO_IS_HASH_TABLE (fo_hash_table));
238   g_return_if_fail (key != NULL);
239   g_return_if_fail (FO_IS_OBJECT (key));
240 
241   g_hash_table_replace (fo_hash_table->hash_table,
242 			g_object_ref(key),
243 			g_object_ref(value));
244 }
245 
246 /**
247  * fo_hash_table_remove:
248  * @fo_hash_table: #FoHashTable from which to remove a key-value pair.
249  * @key:           Key of pair to remove.
250  * @error:         #GError with information about error that occurred.
251  *
252  * Removes the key-value pair with key matching @key from
253  * @fo_hash_table.
254  *
255  * Return value: %TRUE is successful.
256  **/
257 gboolean
fo_hash_table_remove(FoHashTable * fo_hash_table,FoObject * key,GError ** error G_GNUC_UNUSED)258 fo_hash_table_remove (FoHashTable *fo_hash_table,
259 		      FoObject   *key,
260 		      GError   **error G_GNUC_UNUSED)
261 {
262   g_return_val_if_fail (fo_hash_table != NULL, FALSE);
263   g_return_val_if_fail (FO_IS_HASH_TABLE (fo_hash_table), FALSE);
264   g_return_val_if_fail (key != NULL, FALSE);
265   g_return_val_if_fail (FO_IS_OBJECT (key), FALSE);
266 
267   return g_hash_table_remove (fo_hash_table->hash_table,
268 			      g_object_ref(key));
269 }
270 
271 /**
272  * fo_hash_table_lookup:
273  * @fo_hash_table: #FoHashTable in which to look.
274  * @key:           Key value against which to compare.
275  * @error:         #GError with information about error that occurred.
276  *
277  * Gets the value associated with @key in @fo_hash_table.
278  *
279  * Return value: The value, or %NULL if no matching key.
280  **/
281 FoObject *
fo_hash_table_lookup(FoHashTable * fo_hash_table,FoObject * key,GError ** error G_GNUC_UNUSED)282 fo_hash_table_lookup (FoHashTable *fo_hash_table,
283 		      FoObject    *key,
284 		      GError     **error G_GNUC_UNUSED)
285 {
286   g_return_val_if_fail (fo_hash_table != NULL, NULL);
287   g_return_val_if_fail (FO_IS_HASH_TABLE (fo_hash_table), NULL);
288   g_return_val_if_fail (key != NULL, NULL);
289   g_return_val_if_fail (FO_IS_OBJECT (key), NULL);
290 
291   return g_hash_table_lookup (fo_hash_table->hash_table,
292 			      key);
293 }
294 
295 /**
296  * fo_hash_table_size:
297  * @fo_hash_table: #FoHashTable for which to get size.
298  *
299  * Gets the number of key-value pairs in @fo_hash_table.
300  *
301  * Return value: Number of key-value pairs.
302  **/
303 guint
fo_hash_table_size(FoHashTable * fo_hash_table)304 fo_hash_table_size (FoHashTable *fo_hash_table)
305 {
306     return g_hash_table_size (fo_hash_table->hash_table);
307 }
308 
309 /**
310  * fo_hash_table_error_quark:
311  *
312  * Get the error quark for #FoHashTable.
313  *
314  * If the quark does not yet exist, create it.
315  *
316  * Return value: Quark associated with #FoHashTable errors.
317  **/
318 GQuark
fo_hash_table_error_quark(void)319 fo_hash_table_error_quark (void)
320 {
321   static GQuark quark = 0;
322   if (quark == 0)
323     quark = g_quark_from_static_string ("FoHashTable error");
324   return quark;
325 }
326 
327 const char *fo_hash_table_error_messages [] = {
328   N_("Invalid hash_table for context."),
329 };
330