table.c
资源名称:c.rar [点击查看]
上传用户:shmaik
上传日期:2014-06-01
资源大小:45093k
文件大小:3k
源码类别:

VC书籍

开发平台:

C/C++

  1. static char rcsid[] = "$Id: H:/drh/idioms/book/RCS/table.doc,v 1.13 1997/10/27 23:10:11 drh Exp $";
  2. #include <limits.h>
  3. #include <stddef.h>
  4. #include "mem.h"
  5. #include "assert.h"
  6. #include "table.h"
  7. #define T Table_T
  8. struct T {
  9. int size;
  10. int (*cmp)(const void *x, const void *y);
  11. unsigned (*hash)(const void *key);
  12. int length;
  13. unsigned timestamp;
  14. struct binding {
  15. struct binding *link;
  16. const void *key;
  17. void *value;
  18. } **buckets;
  19. };
  20. static int cmpatom(const void *x, const void *y) {
  21. return x != y;
  22. }
  23. static unsigned hashatom(const void *key) {
  24. return (unsigned long)key>>2;
  25. }
  26. T Table_new(int hint,
  27. int cmp(const void *x, const void *y),
  28. unsigned hash(const void *key)) {
  29. T table;
  30. int i;
  31. static int primes[] = { 509, 509, 1021, 2053, 4093,
  32. 8191, 16381, 32771, 65521, INT_MAX };
  33. assert(hint >= 0);
  34. for (i = 1; primes[i] < hint; i++)
  35. ;
  36. table = ALLOC(sizeof (*table) +
  37. primes[i-1]*sizeof (table->buckets[0]));
  38. table->size = primes[i-1];
  39. table->cmp  = cmp  ?  cmp : cmpatom;
  40. table->hash = hash ? hash : hashatom;
  41. table->buckets = (struct binding **)(table + 1);
  42. for (i = 0; i < table->size; i++)
  43. table->buckets[i] = NULL;
  44. table->length = 0;
  45. table->timestamp = 0;
  46. return table;
  47. }
  48. void *Table_get(T table, const void *key) {
  49. int i;
  50. struct binding *p;
  51. assert(table);
  52. assert(key);
  53. i = (*table->hash)(key)%table->size;
  54. for (p = table->buckets[i]; p; p = p->link)
  55. if ((*table->cmp)(key, p->key) == 0)
  56. break;
  57. return p ? p->value : NULL;
  58. }
  59. void *Table_put(T table, const void *key, void *value) {
  60. int i;
  61. struct binding *p;
  62. void *prev;
  63. assert(table);
  64. assert(key);
  65. i = (*table->hash)(key)%table->size;
  66. for (p = table->buckets[i]; p; p = p->link)
  67. if ((*table->cmp)(key, p->key) == 0)
  68. break;
  69. if (p == NULL) {
  70. NEW(p);
  71. p->key = key;
  72. p->link = table->buckets[i];
  73. table->buckets[i] = p;
  74. table->length++;
  75. prev = NULL;
  76. } else
  77. prev = p->value;
  78. p->value = value;
  79. table->timestamp++;
  80. return prev;
  81. }
  82. int Table_length(T table) {
  83. assert(table);
  84. return table->length;
  85. }
  86. void Table_map(T table,
  87. void apply(const void *key, void **value, void *cl),
  88. void *cl) {
  89. int i;
  90. unsigned stamp;
  91. struct binding *p;
  92. assert(table);
  93. assert(apply);
  94. stamp = table->timestamp;
  95. for (i = 0; i < table->size; i++)
  96. for (p = table->buckets[i]; p; p = p->link) {
  97. apply(p->key, &p->value, cl);
  98. assert(table->timestamp == stamp);
  99. }
  100. }
  101. void *Table_remove(T table, const void *key) {
  102. int i;
  103. struct binding **pp;
  104. assert(table);
  105. assert(key);
  106. table->timestamp++;
  107. i = (*table->hash)(key)%table->size;
  108. for (pp = &table->buckets[i]; *pp; pp = &(*pp)->link)
  109. if ((*table->cmp)(key, (*pp)->key) == 0) {
  110. struct binding *p = *pp;
  111. void *value = p->value;
  112. *pp = p->link;
  113. FREE(p);
  114. table->length--;
  115. return value;
  116. }
  117. return NULL;
  118. }
  119. void **Table_toArray(T table, void *end) {
  120. int i, j = 0;
  121. void **array;
  122. struct binding *p;
  123. assert(table);
  124. array = ALLOC((2*table->length + 1)*sizeof (*array));
  125. for (i = 0; i < table->size; i++)
  126. for (p = table->buckets[i]; p; p = p->link) {
  127. array[j++] = (void *)p->key;
  128. array[j++] = p->value;
  129. }
  130. array[j] = end;
  131. return array;
  132. }
  133. void Table_free(T *table) {
  134. assert(table && *table);
  135. if ((*table)->length > 0) {
  136. int i;
  137. struct binding *p, *q;
  138. for (i = 0; i < (*table)->size; i++)
  139. for (p = (*table)->buckets[i]; p; p = q) {
  140. q = p->link;
  141. FREE(p);
  142. }
  143. }
  144. FREE(*table);
  145. }