Updates to Tomato RAF including NGINX && PHP
[tomato.git] / release / src / router / glib / grel.c
blob4358cdcebafdaf9512f7b52ecc9dd7ad5dd86712
1 /* GLIB - Library of useful routines for C programming
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 * Modified by the GLib Team and others 1997-1999. See the AUTHORS
21 * file for a list of people on the GLib Team. See the ChangeLog
22 * files for a list of changes. These files are distributed with
23 * GLib at ftp://ftp.gtk.org/pub/gtk/.
26 /*
27 * MT safe
30 #include "glib.h"
31 #include <stdarg.h>
32 #include <string.h>
34 typedef struct _GRealRelation GRealRelation;
35 typedef struct _GRealTuples GRealTuples;
37 struct _GRealRelation
39 gint fields;
40 gint current_field;
42 GHashTable *all_tuples;
43 GHashTable **hashed_tuple_tables;
44 GMemChunk *tuple_chunk;
46 gint count;
49 struct _GRealTuples
51 gint len;
52 gint width;
53 gpointer *data;
56 static gboolean
57 tuple_equal_2 (gconstpointer v_a,
58 gconstpointer v_b)
60 gpointer* a = (gpointer*) v_a;
61 gpointer* b = (gpointer*) v_b;
63 return a[0] == b[0] && a[1] == b[1];
66 static guint
67 tuple_hash_2 (gconstpointer v_a)
69 gpointer* a = (gpointer*) v_a;
71 return (gulong)a[0] ^ (gulong)a[1];
74 static GHashFunc
75 tuple_hash (gint fields)
77 switch (fields)
79 case 2:
80 return tuple_hash_2;
81 default:
82 g_error ("no tuple hash for %d", fields);
85 return NULL;
88 static GCompareFunc
89 tuple_equal (gint fields)
91 switch (fields)
93 case 2:
94 return tuple_equal_2;
95 default:
96 g_error ("no tuple equal for %d", fields);
99 return NULL;
102 GRelation*
103 g_relation_new (gint fields)
105 GRealRelation* rel = g_new0 (GRealRelation, 1);
107 rel->fields = fields;
108 rel->tuple_chunk = g_mem_chunk_new ("Relation Chunk",
109 fields * sizeof (gpointer),
110 fields * sizeof (gpointer) * 128,
111 G_ALLOC_AND_FREE);
112 rel->all_tuples = g_hash_table_new (tuple_hash (fields), tuple_equal (fields));
113 rel->hashed_tuple_tables = g_new0 (GHashTable*, fields);
115 return (GRelation*) rel;
118 static void
119 g_relation_free_array (gpointer key, gpointer value, gpointer user_data)
121 g_hash_table_destroy ((GHashTable*) value);
124 void
125 g_relation_destroy (GRelation *relation)
127 GRealRelation *rel = (GRealRelation *) relation;
128 gint i;
130 if (rel)
132 g_hash_table_destroy (rel->all_tuples);
133 g_mem_chunk_destroy (rel->tuple_chunk);
135 for (i = 0; i < rel->fields; i += 1)
137 if (rel->hashed_tuple_tables[i])
139 g_hash_table_foreach (rel->hashed_tuple_tables[i], g_relation_free_array, NULL);
140 g_hash_table_destroy (rel->hashed_tuple_tables[i]);
144 g_free (rel->hashed_tuple_tables);
145 g_free (rel);
149 void
150 g_relation_index (GRelation *relation,
151 gint field,
152 GHashFunc hash_func,
153 GCompareFunc key_compare_func)
155 GRealRelation *rel = (GRealRelation *) relation;
157 g_return_if_fail (relation != NULL);
159 g_return_if_fail (rel->count == 0 && rel->hashed_tuple_tables[field] == NULL);
161 rel->hashed_tuple_tables[field] = g_hash_table_new (hash_func, key_compare_func);
164 void
165 g_relation_insert (GRelation *relation,
166 ...)
168 GRealRelation *rel = (GRealRelation *) relation;
169 gpointer* tuple = g_chunk_new (gpointer, rel->tuple_chunk);
170 va_list args;
171 gint i;
173 va_start(args, relation);
175 for (i = 0; i < rel->fields; i += 1)
176 tuple[i] = va_arg(args, gpointer);
178 va_end(args);
180 g_hash_table_insert (rel->all_tuples, tuple, tuple);
182 rel->count += 1;
184 for (i = 0; i < rel->fields; i += 1)
186 GHashTable *table;
187 gpointer key;
188 GHashTable *per_key_table;
190 table = rel->hashed_tuple_tables[i];
192 if (table == NULL)
193 continue;
195 key = tuple[i];
196 per_key_table = g_hash_table_lookup (table, key);
198 if (per_key_table == NULL)
200 per_key_table = g_hash_table_new (tuple_hash (rel->fields), tuple_equal (rel->fields));
201 g_hash_table_insert (table, key, per_key_table);
204 g_hash_table_insert (per_key_table, tuple, tuple);
208 static void
209 g_relation_delete_tuple (gpointer tuple_key,
210 gpointer tuple_value,
211 gpointer user_data)
213 gpointer *tuple = (gpointer*) tuple_value;
214 GRealRelation *rel = (GRealRelation *) user_data;
215 gint j;
217 g_assert (tuple_key == tuple_value);
219 for (j = 0; j < rel->fields; j += 1)
221 GHashTable *one_table = rel->hashed_tuple_tables[j];
222 gpointer one_key;
223 GHashTable *per_key_table;
225 if (one_table == NULL)
226 continue;
228 if (j == rel->current_field)
229 /* can't delete from the table we're foreaching in */
230 continue;
232 one_key = tuple[j];
234 per_key_table = g_hash_table_lookup (one_table, one_key);
236 g_hash_table_remove (per_key_table, tuple);
239 g_hash_table_remove (rel->all_tuples, tuple);
241 rel->count -= 1;
244 gint
245 g_relation_delete (GRelation *relation,
246 gconstpointer key,
247 gint field)
249 GRealRelation *rel = (GRealRelation *) relation;
250 GHashTable *table = rel->hashed_tuple_tables[field];
251 GHashTable *key_table;
252 gint count = rel->count;
254 g_return_val_if_fail (relation != NULL, 0);
255 g_return_val_if_fail (table != NULL, 0);
257 key_table = g_hash_table_lookup (table, key);
259 if (!key_table)
260 return 0;
262 rel->current_field = field;
264 g_hash_table_foreach (key_table, g_relation_delete_tuple, rel);
266 g_hash_table_remove (table, key);
268 g_hash_table_destroy (key_table);
270 /* @@@ FIXME: Remove empty hash tables. */
272 return count - rel->count;
275 static void
276 g_relation_select_tuple (gpointer tuple_key,
277 gpointer tuple_value,
278 gpointer user_data)
280 gpointer *tuple = (gpointer*) tuple_value;
281 GRealTuples *tuples = (GRealTuples*) user_data;
282 gint stride = sizeof (gpointer) * tuples->width;
284 g_assert (tuple_key == tuple_value);
286 memcpy (tuples->data + (tuples->len * tuples->width),
287 tuple,
288 stride);
290 tuples->len += 1;
293 GTuples*
294 g_relation_select (GRelation *relation,
295 gconstpointer key,
296 gint field)
298 GRealRelation *rel = (GRealRelation *) relation;
299 GHashTable *table = rel->hashed_tuple_tables[field];
300 GHashTable *key_table;
301 GRealTuples *tuples = g_new0 (GRealTuples, 1);
302 gint count;
304 g_return_val_if_fail (relation != NULL, NULL);
305 g_return_val_if_fail (table != NULL, NULL);
307 key_table = g_hash_table_lookup (table, key);
309 if (!key_table)
310 return (GTuples*)tuples;
312 count = g_relation_count (relation, key, field);
314 tuples->data = g_malloc (sizeof (gpointer) * rel->fields * count);
315 tuples->width = rel->fields;
317 g_hash_table_foreach (key_table, g_relation_select_tuple, tuples);
319 g_assert (count == tuples->len);
321 return (GTuples*)tuples;
324 gint
325 g_relation_count (GRelation *relation,
326 gconstpointer key,
327 gint field)
329 GRealRelation *rel = (GRealRelation *) relation;
330 GHashTable *table = rel->hashed_tuple_tables[field];
331 GHashTable *key_table;
333 g_return_val_if_fail (relation != NULL, 0);
334 g_return_val_if_fail (table != NULL, 0);
336 key_table = g_hash_table_lookup (table, key);
338 if (!key_table)
339 return 0;
341 return g_hash_table_size (key_table);
344 gboolean
345 g_relation_exists (GRelation *relation, ...)
347 GRealRelation *rel = (GRealRelation *) relation;
348 gpointer* tuple = g_chunk_new (gpointer, rel->tuple_chunk);
349 va_list args;
350 gint i;
351 gboolean result;
353 va_start(args, relation);
355 for (i = 0; i < rel->fields; i += 1)
356 tuple[i] = va_arg(args, gpointer);
358 va_end(args);
360 result = g_hash_table_lookup (rel->all_tuples, tuple) != NULL;
362 g_mem_chunk_free (rel->tuple_chunk, tuple);
364 return result;
367 void
368 g_tuples_destroy (GTuples *tuples0)
370 GRealTuples *tuples = (GRealTuples*) tuples0;
372 if (tuples)
374 g_free (tuples->data);
375 g_free (tuples);
379 gpointer
380 g_tuples_index (GTuples *tuples0,
381 gint index,
382 gint field)
384 GRealTuples *tuples = (GRealTuples*) tuples0;
386 g_return_val_if_fail (tuples0 != NULL, NULL);
387 g_return_val_if_fail (field < tuples->width, NULL);
389 return tuples->data[index * tuples->width + field];
392 /* Print
395 static void
396 g_relation_print_one (gpointer tuple_key,
397 gpointer tuple_value,
398 gpointer user_data)
400 gint i;
401 GString *gstring;
402 GRealRelation* rel = (GRealRelation*) user_data;
403 gpointer* tuples = (gpointer*) tuple_value;
405 gstring = g_string_new ("[");
407 for (i = 0; i < rel->fields; i += 1)
409 g_string_sprintfa (gstring, "%p", tuples[i]);
411 if (i < (rel->fields - 1))
412 g_string_append (gstring, ",");
415 g_string_append (gstring, "]");
416 g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, gstring->str);
417 g_string_free (gstring, TRUE);
420 static void
421 g_relation_print_index (gpointer tuple_key,
422 gpointer tuple_value,
423 gpointer user_data)
425 GRealRelation* rel = (GRealRelation*) user_data;
426 GHashTable* table = (GHashTable*) tuple_value;
428 g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "*** key %p", tuple_key);
430 g_hash_table_foreach (table,
431 g_relation_print_one,
432 rel);
435 void
436 g_relation_print (GRelation *relation)
438 gint i;
439 GRealRelation* rel = (GRealRelation*) relation;
441 g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "*** all tuples (%d)", rel->count);
443 g_hash_table_foreach (rel->all_tuples,
444 g_relation_print_one,
445 rel);
447 for (i = 0; i < rel->fields; i += 1)
449 if (rel->hashed_tuple_tables[i] == NULL)
450 continue;
452 g_log (g_log_domain_glib, G_LOG_LEVEL_INFO, "*** index %d", i);
454 g_hash_table_foreach (rel->hashed_tuple_tables[i],
455 g_relation_print_index,
456 rel);