summaryrefslogtreecommitdiffstats
path: root/tools/hash.c
diff options
context:
space:
mode:
authorunknown <unknown@unknown>2009-10-23 04:29:39 +0000
committerunknown <unknown@unknown>2009-10-23 04:29:39 +0000
commitddf5c42f67757000d6ec7686b92a667c2a252dca (patch)
treee070b352fab4b285b7a4ea547d0cbfff9b7fb4d1 /tools/hash.c
downloadiksemel-ddf5c42f67757000d6ec7686b92a667c2a252dca.tar.gz
iksemel-ddf5c42f67757000d6ec7686b92a667c2a252dca.tar.xz
iksemel-ddf5c42f67757000d6ec7686b92a667c2a252dca.zip
Imported from iksemel-1.3.tar.gz.
Diffstat (limited to 'tools/hash.c')
-rw-r--r--tools/hash.c144
1 files changed, 144 insertions, 0 deletions
diff --git a/tools/hash.c b/tools/hash.c
new file mode 100644
index 0000000..8ba83a0
--- /dev/null
+++ b/tools/hash.c
@@ -0,0 +1,144 @@
+/* iksemel (XML parser for Jabber)
+** Copyright (C) 2000-2003 Gurer Ozen <madcat@e-kolay.net>
+** This code is free software; you can redistribute it and/or
+** modify it under the terms of GNU Lesser General Public License.
+*/
+
+#include "common.h"
+#include "iksemel.h"
+
+static unsigned int
+hash_str (const char *str)
+{
+ const char *p;
+ unsigned int h = 0;
+
+ for (p = str; *p != '\0'; p++) {
+ h = ( h << 5 ) - h + *p;
+ }
+ return h;
+}
+
+struct item {
+ char *name;
+ unsigned int count;
+ struct item *next;
+};
+
+struct hash_s {
+ struct item **table;
+ unsigned int size;
+ unsigned int count;
+ ikstack *s;
+};
+
+typedef struct hash_s hash;
+
+hash *
+hash_new (unsigned int table_size)
+{
+ hash *h;
+
+ h = malloc (sizeof (struct hash_s));
+ if (!h) return NULL;
+ h->table = calloc (sizeof (struct item *), table_size);
+ if (!h->table) {
+ free (h);
+ return NULL;
+ }
+ h->s = iks_stack_new (sizeof (hash) * 128, 8192);
+ if (!h->s) {
+ free (h->table);
+ free (h);
+ return NULL;
+ }
+ h->size = table_size;
+ h->count = 0;
+
+ return h;
+}
+
+char *
+hash_insert (hash *h, const char *name)
+{
+ struct item *t, *p;
+ unsigned int val;
+
+ val = hash_str (name) % h->size;
+ h->count++;
+
+ for (t = h->table[val]; t; t = t->next) {
+ if (strcmp (t->name, name) == 0)
+ break;
+ }
+ if (NULL == t) {
+ t = iks_stack_alloc (h->s, sizeof (struct item));
+ if (!t) return NULL;
+ t->name = iks_stack_strdup (h->s, name, 0);
+ t->count = 0;
+ t->next = NULL;
+ p = h->table[val];
+ if (!p) {
+ h->table[val] = t;
+ } else {
+ while (1) {
+ if (p->next == NULL) {
+ p->next = t;
+ break;
+ }
+ p = p->next;
+ }
+ }
+ }
+ t->count++;
+
+ return t->name;
+}
+
+static int
+my_cmp (const void *a, const void *b)
+{
+ unsigned int c1, c2;
+
+ c1 = (*(struct item **)a)->count;
+ c2 = (*(struct item **)b)->count;
+
+ if (c1 > c2)
+ return -1;
+ else if (c1 == c2)
+ return 0;
+ else
+ return 1;
+}
+
+void
+hash_print (hash *h, char *title_fmt, char *line_fmt)
+{
+ struct item **tags, *t;
+ unsigned int i = 0, pos = 0;
+
+ tags = calloc (sizeof (struct tag *), h->count);
+
+ for (; i < h->size; i ++) {
+ for (t = h->table[i]; t; t = t->next) {
+ tags[pos++] = t;
+ }
+ }
+
+ qsort (tags, pos, sizeof (struct item *), my_cmp);
+
+ printf (title_fmt, pos);
+ for (i = 0; i < pos; i++) {
+ printf (line_fmt, tags[i]->name, tags[i]->count);
+ }
+
+ free (tags);
+}
+
+void
+hash_delete (hash *h)
+{
+ iks_stack_delete (h->s);
+ free (h->table);
+ free (h);
+}