hash.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /* iksemel (XML parser for Jabber)
  2. ** Copyright (C) 2000-2003 Gurer Ozen <madcat@e-kolay.net>
  3. ** This code is free software; you can redistribute it and/or
  4. ** modify it under the terms of GNU Lesser General Public License.
  5. */
  6. #include "common.h"
  7. #include "iksemel.h"
  8. static unsigned int
  9. hash_str (const char *str)
  10. {
  11. const char *p;
  12. unsigned int h = 0;
  13. for (p = str; *p != '\0'; p++) {
  14. h = ( h << 5 ) - h + *p;
  15. }
  16. return h;
  17. }
  18. struct item {
  19. char *name;
  20. unsigned int count;
  21. struct item *next;
  22. };
  23. struct hash_s {
  24. struct item **table;
  25. unsigned int size;
  26. unsigned int count;
  27. ikstack *s;
  28. };
  29. typedef struct hash_s hash;
  30. hash *
  31. hash_new (unsigned int table_size)
  32. {
  33. hash *h;
  34. h = malloc (sizeof (struct hash_s));
  35. if (!h) return NULL;
  36. h->table = calloc (sizeof (struct item *), table_size);
  37. if (!h->table) {
  38. free (h);
  39. return NULL;
  40. }
  41. h->s = iks_stack_new (sizeof (hash) * 128, 8192);
  42. if (!h->s) {
  43. free (h->table);
  44. free (h);
  45. return NULL;
  46. }
  47. h->size = table_size;
  48. h->count = 0;
  49. return h;
  50. }
  51. char *
  52. hash_insert (hash *h, const char *name)
  53. {
  54. struct item *t, *p;
  55. unsigned int val;
  56. val = hash_str (name) % h->size;
  57. h->count++;
  58. for (t = h->table[val]; t; t = t->next) {
  59. if (strcmp (t->name, name) == 0)
  60. break;
  61. }
  62. if (NULL == t) {
  63. t = iks_stack_alloc (h->s, sizeof (struct item));
  64. if (!t) return NULL;
  65. t->name = iks_stack_strdup (h->s, name, 0);
  66. t->count = 0;
  67. t->next = NULL;
  68. p = h->table[val];
  69. if (!p) {
  70. h->table[val] = t;
  71. } else {
  72. while (1) {
  73. if (p->next == NULL) {
  74. p->next = t;
  75. break;
  76. }
  77. p = p->next;
  78. }
  79. }
  80. }
  81. t->count++;
  82. return t->name;
  83. }
  84. static int
  85. my_cmp (const void *a, const void *b)
  86. {
  87. unsigned int c1, c2;
  88. c1 = (*(struct item **)a)->count;
  89. c2 = (*(struct item **)b)->count;
  90. if (c1 > c2)
  91. return -1;
  92. else if (c1 == c2)
  93. return 0;
  94. else
  95. return 1;
  96. }
  97. void
  98. hash_print (hash *h, char *title_fmt, char *line_fmt)
  99. {
  100. struct item **tags, *t;
  101. unsigned int i = 0, pos = 0;
  102. tags = calloc (sizeof (struct tag *), h->count);
  103. for (; i < h->size; i ++) {
  104. for (t = h->table[i]; t; t = t->next) {
  105. tags[pos++] = t;
  106. }
  107. }
  108. qsort (tags, pos, sizeof (struct item *), my_cmp);
  109. printf (title_fmt, pos);
  110. for (i = 0; i < pos; i++) {
  111. printf (line_fmt, tags[i]->name, tags[i]->count);
  112. }
  113. free (tags);
  114. }
  115. void
  116. hash_delete (hash *h)
  117. {
  118. iks_stack_delete (h->s);
  119. free (h->table);
  120. free (h);
  121. }