00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <config.h>
00031
00032 #include <isc/heap.h>
00033 #include <isc/magic.h>
00034 #include <isc/mem.h>
00035 #include <isc/string.h>
00036 #include <isc/util.h>
00037
00038
00039
00040
00041
00042
00043
00044
00045 #define heap_parent(i) ((i) >> 1)
00046 #define heap_left(i) ((i) << 1)
00047
00048
00049 #define SIZE_INCREMENT 1024
00050
00051 #define HEAP_MAGIC ISC_MAGIC('H', 'E', 'A', 'P')
00052 #define VALID_HEAP(h) ISC_MAGIC_VALID(h, HEAP_MAGIC)
00053
00054
00055
00056
00057
00058
00059 #define HEAPCONDITION(i) ((i) == 1 || \
00060 ! heap->compare(heap->array[(i)], \
00061 heap->array[heap_parent(i)]))
00062
00063
00064 struct isc_heap {
00065 unsigned int magic;
00066 isc_mem_t * mctx;
00067 unsigned int size;
00068 unsigned int size_increment;
00069 unsigned int last;
00070 void **array;
00071 isc_heapcompare_t compare;
00072 isc_heapindex_t index;
00073 };
00074
00075 isc_result_t
00076 isc_heap_create(isc_mem_t *mctx, isc_heapcompare_t compare,
00077 isc_heapindex_t idx, unsigned int size_increment,
00078 isc_heap_t **heapp)
00079 {
00080 isc_heap_t *heap;
00081
00082 REQUIRE(heapp != NULL && *heapp == NULL);
00083 REQUIRE(compare != NULL);
00084
00085 heap = isc_mem_get(mctx, sizeof(*heap));
00086 if (heap == NULL)
00087 return (ISC_R_NOMEMORY);
00088 heap->magic = HEAP_MAGIC;
00089 heap->size = 0;
00090 heap->mctx = NULL;
00091 isc_mem_attach(mctx, &heap->mctx);
00092 if (size_increment == 0)
00093 heap->size_increment = SIZE_INCREMENT;
00094 else
00095 heap->size_increment = size_increment;
00096 heap->last = 0;
00097 heap->array = NULL;
00098 heap->compare = compare;
00099 heap->index = idx;
00100
00101 *heapp = heap;
00102
00103 return (ISC_R_SUCCESS);
00104 }
00105
00106 void
00107 isc_heap_destroy(isc_heap_t **heapp) {
00108 isc_heap_t *heap;
00109
00110 REQUIRE(heapp != NULL);
00111 heap = *heapp;
00112 REQUIRE(VALID_HEAP(heap));
00113
00114 if (heap->array != NULL)
00115 isc_mem_put(heap->mctx, heap->array,
00116 heap->size * sizeof(void *));
00117 heap->magic = 0;
00118 isc_mem_putanddetach(&heap->mctx, heap, sizeof(*heap));
00119
00120 *heapp = NULL;
00121 }
00122
00123 static isc_boolean_t
00124 resize(isc_heap_t *heap) {
00125 void **new_array;
00126 unsigned int new_size;
00127
00128 REQUIRE(VALID_HEAP(heap));
00129
00130 new_size = heap->size + heap->size_increment;
00131 new_array = isc_mem_get(heap->mctx, new_size * sizeof(void *));
00132 if (new_array == NULL)
00133 return (ISC_FALSE);
00134 if (heap->array != NULL) {
00135 memmove(new_array, heap->array, heap->size * sizeof(void *));
00136 isc_mem_put(heap->mctx, heap->array,
00137 heap->size * sizeof(void *));
00138 }
00139 heap->size = new_size;
00140 heap->array = new_array;
00141
00142 return (ISC_TRUE);
00143 }
00144
00145 static void
00146 float_up(isc_heap_t *heap, unsigned int i, void *elt) {
00147 unsigned int p;
00148
00149 for (p = heap_parent(i) ;
00150 i > 1 && heap->compare(elt, heap->array[p]) ;
00151 i = p, p = heap_parent(i)) {
00152 heap->array[i] = heap->array[p];
00153 if (heap->index != NULL)
00154 (heap->index)(heap->array[i], i);
00155 }
00156 heap->array[i] = elt;
00157 if (heap->index != NULL)
00158 (heap->index)(heap->array[i], i);
00159
00160 INSIST(HEAPCONDITION(i));
00161 }
00162
00163 static void
00164 sink_down(isc_heap_t *heap, unsigned int i, void *elt) {
00165 unsigned int j, size, half_size;
00166 size = heap->last;
00167 half_size = size / 2;
00168 while (i <= half_size) {
00169
00170 j = heap_left(i);
00171 if (j < size && heap->compare(heap->array[j+1],
00172 heap->array[j]))
00173 j++;
00174 if (heap->compare(elt, heap->array[j]))
00175 break;
00176 heap->array[i] = heap->array[j];
00177 if (heap->index != NULL)
00178 (heap->index)(heap->array[i], i);
00179 i = j;
00180 }
00181 heap->array[i] = elt;
00182 if (heap->index != NULL)
00183 (heap->index)(heap->array[i], i);
00184
00185 INSIST(HEAPCONDITION(i));
00186 }
00187
00188 isc_result_t
00189 isc_heap_insert(isc_heap_t *heap, void *elt) {
00190 unsigned int new_last;
00191
00192 REQUIRE(VALID_HEAP(heap));
00193
00194 new_last = heap->last + 1;
00195 RUNTIME_CHECK(new_last > 0);
00196 if (new_last >= heap->size && !resize(heap))
00197 return (ISC_R_NOMEMORY);
00198 heap->last = new_last;
00199
00200 float_up(heap, new_last, elt);
00201
00202 return (ISC_R_SUCCESS);
00203 }
00204
00205 void
00206 isc_heap_delete(isc_heap_t *heap, unsigned int idx) {
00207 void *elt;
00208 isc_boolean_t less;
00209
00210 REQUIRE(VALID_HEAP(heap));
00211 REQUIRE(idx >= 1 && idx <= heap->last);
00212
00213 if (idx == heap->last) {
00214 heap->array[heap->last] = NULL;
00215 heap->last--;
00216 } else {
00217 elt = heap->array[heap->last];
00218 heap->array[heap->last] = NULL;
00219 heap->last--;
00220
00221 less = heap->compare(elt, heap->array[idx]);
00222 heap->array[idx] = elt;
00223 if (less)
00224 float_up(heap, idx, heap->array[idx]);
00225 else
00226 sink_down(heap, idx, heap->array[idx]);
00227 }
00228 }
00229
00230 void
00231 isc_heap_increased(isc_heap_t *heap, unsigned int idx) {
00232 REQUIRE(VALID_HEAP(heap));
00233 REQUIRE(idx >= 1 && idx <= heap->last);
00234
00235 float_up(heap, idx, heap->array[idx]);
00236 }
00237
00238 void
00239 isc_heap_decreased(isc_heap_t *heap, unsigned int idx) {
00240 REQUIRE(VALID_HEAP(heap));
00241 REQUIRE(idx >= 1 && idx <= heap->last);
00242
00243 sink_down(heap, idx, heap->array[idx]);
00244 }
00245
00246 void *
00247 isc_heap_element(isc_heap_t *heap, unsigned int idx) {
00248 REQUIRE(VALID_HEAP(heap));
00249 REQUIRE(idx >= 1);
00250
00251 if (idx <= heap->last)
00252 return (heap->array[idx]);
00253 return (NULL);
00254 }
00255
00256 void
00257 isc_heap_foreach(isc_heap_t *heap, isc_heapaction_t action, void *uap) {
00258 unsigned int i;
00259
00260 REQUIRE(VALID_HEAP(heap));
00261 REQUIRE(action != NULL);
00262
00263 for (i = 1 ; i <= heap->last ; i++)
00264 (action)(heap->array[i], uap);
00265 }